Running functions inside of a view Oracle SQL - sql

I'm trying to create a view that returns all the bookings that are between a certain date. I have a table called Booking which includes the columns:
startDate date,
noOfDays int,
and more columns which aren't relevant to the view I'm trying to create.
I'm trying to run the following query to create a view but it seems to fail with the error "ORA-00904: "DATEADD": Invalid identifier"
CREATE VIEW Present_bookings AS
SELECT * FROM Booking
WHERE startDate => '2018-03-12'
AND startDate <= DATEADD(Booking.startDate, 'YYYY-MM-DD', Booking.noOfDays);
What am I doing wrong?

The logic is not correct. All startdate is less than startdate+5 days. Are you sure about this condition? If yes, then it will be simplied as:
CREATE VIEW Present_bookings AS
select *
FROM Booking
where startDate >= to_date('2018-03-12','YYYY-MM-DD')
OR probably you are thinking about this:
CREATE VIEW Present_bookings AS
select *
FROM Booking
where startDate between to_date('2018-03-12','YYYY-MM-DD')
and to_date('2018-03-17','YYYY-MM-DD')

There are a couple of things wrong with your query. But the primary thing is that DATEADD() is not a valid function in Oracle. Oracle date arithmetic is very simple; just add noOfDays to startDate:
CREATE VIEW Present_bookings AS
SELECT * FROM Booking
WHERE startDate >= DATE'2018-03-12'
AND startDate <= startDate + noOfDays;
Note that I changed your operator => to >= and added the DATE keyword to the date literal 2018-03-12 to tell Oracle that it's a date.
As an aside, I don't know what the second condition is supposed to do; startDate should always be less than startDate + noOfDays unless noOfDays is negative. I think you might want something like the following:
CREATE VIEW Present_bookings AS
SELECT * FROM Booking
WHERE startDate <= DATE'2018-03-12'
AND DATE'2018-03-12' <= startDate + noOfDays;
OR
CREATE VIEW Present_bookings AS
SELECT * FROM Booking
WHERE DATE'2018-03-12' BETWEEN startDate AND startDate + noOfDays;

I guess you're looking for a easy way to add a number of days to a date.
Try using interval here:
select sysdate, sysdate + interval '5' day as "FUTURE" from dual;
=>
SYSDATE FUTURE
22.03.2018 14:37:27 27.03.2018 14:37:27
Take care of the '5' as a character, not a number.
This also works with years, months (take care of 29.02 here) etc.

Related

Convert String column to Date in SSRS

I am trying to write a create statement for creating data source in SSRS. My Create Statement is as follows :-
Select TOP(cast(1000 as integer)) Name,
TName,
IName,
IType,
AvgPercent,
FCount,
PCount,
AvgInPages,
CONVERT(VARCHAR(10),RunDate,103) AS RunDate,
CONVERT(TIME(0), RunTime) AS RTime
from Index
where RunDateBetween #StartDate and #EndDate
Currently I have done it like this CONVERT(VARCHAR(10),RunDate,103) AS RDate, but between clause is not working. Between Clause only gives me record for start date and nothing after that. So I want to convert varchar to date I tried using this after searching on web CONVERT(Date,RunDate,103) AS RunDate but that gives me date as well as time whereas I just need date in that column. After lot of searching I am not able to find any concerete solution.Please help me.
How about this?
SELECT TOP 1000 NAME
,TName
,IName
,IType
,AvgPercent
,FCount
,PCount
,AvgInPages
,CAST(RunDate AS DATE) AS RDate
,CONVERT(TIME(0), RunTime) AS RTime
FROM INDEX
WHERE CAST(RunDate AS DATE) BETWEEN #StartDate
AND #EndDate

SQL SELECT STATEMENT FOR TODAY

I have been battling for two days now, please could someone give me a bit of assistance on below. I am trying to select data where a date field/column must equal today's date.
SELECT *
FROM stock
WHERE DATE(PREVSELLPRICE1DATE)=DATE(now());
Please assist if you can, I need to rollout this report.
it is better not to manipulate DATE column using functions like TRUNC to mach the date without hour precision (matching year-month-day), it recommended for performance to use something like:
SELECT *
FROM stock
WHERE PREVSELLPRICE1DATE between trunc(sysdate) and trunc(sysdate+1)
this way you'll compare for the required day only + the TRUNC function will be applied only 2 times instead of on each row.
For sql server below is fine:
SELECT *
FROM stock
WHERE CAST(PREVSELLPRICE1DATE as date) = CAST(GETDATE() as date)
Below script
select cast(getdate() as date)
will give you result:
2017-06-29

Recursive Query for Date Range

I'm trying to create a query so that I can generate a date range between a specific start and end point.
I have the following:
WITH DATE_RANGE(DATE_FOR_SHIFT)
AS (SELECT DATE('2015-04-01')
FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT DATE_FOR_SHIFT + 1 DAY
FROM DATE_RANGE
WHERE DATE_FOR_SHIFT <= #END)
SELECT DATE_FOR_SHIFT
FROM DATE_RANGE;
Output (assuming that #END equals 2015-05-01):
2015-04-01
2015-04-02
2015-04-03
2015-04-04
...
2015-05-01
The output is correct, but I want to be able to change the start and points based on parameters provided rather than having to rewrite the query or have a SQL injection prone query.
How would I rewrite this query in order to accomplish this?
Your SELECT is fine, other than the hard coded start date.
What I think you're missing is wrapping it in either a stored procedure or user defined table function (UDTF). Assuming you'll want to JOIN the date range to other tables, I'd suggest a UDTF.
create function date_range (#str date, #end date)
returns table (date_for_shift date)
language SQL
reads SQL data
return
WITH DATE_RANGE(DATE_FOR_SHIFT)
AS (SELECT #str
FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT DATE_FOR_SHIFT + 1 DAY
FROM DATE_RANGE
WHERE DATE_FOR_SHIFT <= #END)
SELECT DATE_FOR_SHIFT
FROM DATE_RANGE;
Then you'd call it...
select * from table(date_range(date('2015-04-01'),date('2015-05-01'))) as tbl;
However, instead of generating this date range on the fly....consider simply creating a calender (aka dates) table. Basically just a table with dates from say 1900-01-01 to 2500-12-31..or whatever you'd like. Beside the date column, you can include lots of additional columns such as business_day, holiday, ect.. that make life much easier.
Google "SQL calendar table" for plenty of examples.
A bit of playing with this in perl gives me:
#!/opt/myperl/5.20.2/bin/perl
use 5.10.0;
use DBI;
use DBD::DB2;
use Data::Dump;
my $sql = <<EOSQL;
WITH DATE_RANGE(DATE_FOR_SHIFT)
AS (SELECT CAST(? AS DATE)
FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT DATE_FOR_SHIFT + 1 DAY
FROM DATE_RANGE
WHERE DATE_FOR_SHIFT < CAST(? AS DATE))
SELECT DATE_FOR_SHIFT
FROM DATE_RANGE;
EOSQL
my $dbh = DBI->connect('dbi:DB2:sample');
my $sth = $dbh->prepare_cached($sql);
$sth->execute('2015-04-01','2015-05-01');
my $rc = $sth->fetchall_arrayref();
dd($rc);
This does give an error during prepare ("The recursive common table expression "MYSCHEMA.DATE_RANGE" may contain an infinite loop") that I haven't figured out yet, but the fetch does work, the final return goes from 04-01 to 05-01. Hopefully you can port this to your desired language.

SQL: retrieve records between dates in all databases

I would like to select all the records in a table between two dates. I have a query like:
SELECT * FROM <table> WHERE (thedate BETWEEN DATE('2012-04-01') AND DATE('2012-06-30'))
This is fine for HSQL, Oracle, PostgreSQL, but it doesn't work in SQL Server due to the lack of the Date function. Is there a way to get this to work generally for all databases (including SQL Server) or do I need to use an ORM like Hibernate (I know I should, but I'm specifically asking if this can be done in SQL)?
There's no need for the Date(...) as far as i can tell. This example seems to work
DECLARE #TheDate Date = '2012-07-01';
SELECT 'hello' WHERE (#TheDate BETWEEN '2012-04-01' AND '2012-06-30')
--None returned
SET #TheDate = '2012-05-01'
SELECT 'hello' WHERE (#TheDate BETWEEN '2012-04-01' AND '2012-06-30')
--selects hello
Edit Btw worth looking at This Question with the date time answer (will post here just to save effort)
The between statement can cause issues with range boundaries for dates as
BETWEEN '01/01/2009' AND '01/31/2009'
is really interpreted as
BETWEEN '01/01/2009 00:00:00' AND '01/31/2009 00:00:00'
so will miss anything that occurred during the day of Jan 31st. In this case, you will have to use:
myDate >= '01/01/2009 00:00:00' AND myDate < '02/01/2009 00:00:00' --CORRECT!
or
BETWEEN '01/01/2009 00:00:00' AND '01/31/2009 23:59:59' --WRONG! (see update!)
UPDATE: It is entirely possible to have records created within that last second of the day, with a datetime as late as 01/01/2009 23:59:59.997!!
For this reason, the BETWEEN (firstday) AND (lastday 23:59:59) approach is not recommended.
Use the myDate >= (firstday) AND myDate < (Lastday+1) approach instead.
in sql-server I think you may want to look into the
DATEADD ( datepart , number, date )
DATEDIFF ( datepart , startdate , enddate )
but I think you're looking for
CAST ( expression AS data_type )
or
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
usage:
Select * from myTable where thedateToCompare >= CONVERT ( datetime , "dd/mm/yy hh:mi:ss:mmmAM" ) and thedateToCompare <= CONVERT ( datetime , "dd/mm/yy hh:mi:ss:mmmAM" )
something that may change your approach is weather your source 'thedate' column type datetime, smalldatetime or is it stored in a column defined as string?
You may want to check out a link! for more detial on datetime constants that you could use for your string variations.

sqlserver date arithmetic problem

I have a records of events with starttime and endtime for a calendar control.
I want to get the events done on a particular date say 2/28/2009
But the db table has date data in form 2/28/2009 10:00:00, 2/28/2009 12:00:00.
I tried this query in a sproc created in VS 2005 IDE but it didn't work
ALTER PROCEDURE dbo.spSelectBenchEvent
(
#EVENT_DATE DATE // BTW, THIS RETURNS ERROR :CANNOT FIND DATE DATATYPE.
//#EVENT_DATE HAS INVALID DATATYPE
)
AS
BEGIN TRAN
SET NOCOUNT ON;
SELECT ID, EID, BENCHID, PACCODE, START_TIME, END_TIME
FROM tbl_benchbook
WHERE START_TIME=EVENT_DATE
ORDER BY START_TIME
Thanks in advance.
There were many questions related to this one, check out:
Floor a date in SQL server
and for best performance-wise solution check: MS SQL Date Only Without Time
Basically your code could look like:
select
id, eid, benchid, paccode, start_time, end_time
from
tbl_benchbook
where start_time >= dateadd(dd, datediff(dd, 0, #event_date), 0)
and start_time < dateadd(dd, datediff(dd, 0, #event_date)+1, 0)
Based on your updated ques , this should work :
SELECT ID, EID, BENCHID, PACCODE, START_TIME, END_TIME
FROM tbl_benchbook
WHERE START_TIME >= #EVENT_DATE
AND START_TIME < DATEADD(day,1,#EVENT_DATE)
ORDER BY START_TIME
If you wish to evaluate all events on the date 3/29/2009 use the following where cluase.
SELECT *
FROM tableName
WHERE Date >= '2009/03/29' AND Date < '2009/03/30'
The key point to take away here is that in order to capture all records that occured on a given date you need to define a date range that includes all time values for that day.
Make sense?
Cheers, John
--1. you need to make sure there is no time on the parameter
--2. you can just use "+1" on the datetime, to get the next day
enter ALTER PROCEDURE dbo.spSelectBenchEvent
(
#EVENT_DATE DATETIME
)
AS
BEGIN TRAN
SET NOCOUNT ON;
--remove any time from given date
SET #EVENT_DATE=CONVERT(char(10),#EVENT_DATE,111)
SELECT ID, EID, BENCHID, PACCODE, START_TIME, END_TIME
FROM tbl_benchbook
WHERE START_TIME>=#EVENT_DATE AND START_TIME<#EVENT_DATE+1
ORDER BY START_TIME
code here