I have a column called Create_Date which has data in the format like 19-JUN-18 10.27.00.000000000 PM and data type is TIMESTAMP(6).
I am trying to look at date range like yesterday's date or between two dates in Create_Date without using TO_DATE(TO_CHAR(P.CREATE_DATE_TIME,'dd/mon/yy')) and entering the value as '19-JUN-18'.
I want to use Create_Date=SYSDATE-1 OR Create_Date=CURRENT_DATE-1 instead to filter on yesterdays date. Or Use Create_Date>=SYSDATE or Create_Date>=CURRENT_DATE to look at dates greater than or equal to today.
Can someone help?
You could use TRUNC:
SELECT *
FROM tab
WHERE Create_Date >= TRUNC(SYSDATE,'DD') -- -1
-- or between to dates (using date literals)
WHERE Create_Date >= DATE 'yyyy-mm-dd'
AND Create_Date < DATE 'yyyy-mm-dd'
As it's a timestamp I'd cast the truncated (to midnight) current date to a timestamp for clarity; Oracle will use an index on that column even if you leave it as a date, but it doesn't hurt to make it explicit:
where create_date >= cast(trunc(sysdate) as timestamp)
The trunc() function defaults to truncating to midnight; you can explicitly include 'DD' as a second argument if you prefer (for even more clarity, though some would see it as noise).
If you want a range, say yesterday:
where create_date >= cast(trunc(sysdate) - 1 as timestamp)
and create_date < cast(trunc(sysdate) as timestamp)
If you want to specify other dates then you can use timestamp literals, e.g. to see everything for May:
where create_date >= timestamp '2018-05-01 00:00:00'
and create_date < timestamp '2018-06-01 00:00:00'
Related
sql table
here in the table above named carpooling contains a column name start_on which has date time as timestamp i have to write a query to select all the rows having date as 25-11-20 using to_char and to_date.
You write a timestamp literal like this:
timestamp '2020-11-25 00:00:00'
so the full filtering condition will be
where start_on >= timestamp '2020-11-25 00:00:00'
and start_on < timestamp '2020-11-26 00:00:00'
Note that dates and timestamps are different in Oracle, and dates include times down to the second (this is for historical reasons - originally there was only the date type, and timestamp was added much later).
Use the TRUNC function, along with date and interval literals:
SELECT *
FROM CARPOOLING
WHERE START_ON BETWEEN DATE '2020-11-25'
AND (DATE '2020-11-26' - INTERVAL '0.000001' SECOND)
You can simply use to_date, but it's recommended to remove the time when comparing the dates. Otherwise, rows having the same date, but a different time will not be selected. Removing the time can be done using TRUNC.
So you can do something like this:
SELECT * FROM carpooling
WHERE TRUNC(start_on) = TO_DATE('2020-11-25','yyyy.mm.dd');
If you don't want to check the 25th of November 2020, but another data, change the date to match your goal.
I'm trying to get data between two dates that should include seconds
I'm currently using the below code, which works fine; however now it needs to be more precise to include the time.
where h.creation_time >= date '2017-01-01'
and h.CLOSED_TIME >= date '2018-12-16' and h.CLOSED_TIME <= date '2018-12-17'
Here is what I tried changing the code to:
where (h.creation_time >= date '2017-01-01')
and (h.CLOSED_TIME between '2018-12-16 18:19:00' and '2018-12-16 18:20:00')
I should expect the results of everything between 6:19pm and 6:20pm (one minute time frame). Instead it is spitting out the error:
ORA-01861: literal does not match format string
Try to convert them explicitly with to_date().
WHERE h.creation_time >= to_date('2017-01-01', 'YYYY-MM-DD')
AND h.closed_time BETWEEN to_date('2018-12-16 18:19:00', 'YYYY-MM-DD HH24:MI:SS')
AND to_date('2018-12-16 18:20:00', 'YYYY-MM-DD HH24:MI:SS')
A timestamp literal starts with the keyword TIMESTAMP (just as a date literal starts with DATE):
where h.creation_time >= date '2017-01-01'
and h.closed_time between timestamp '2018-12-16 18:19:00' and timestamp '2018-12-16 18:20:00'
In order to take fractions of seconds into account, you shouldn't use BETWEEN however, but:
where h.creation_time >= date '2017-01-01'
and h.closed_time >= timestamp '2018-12-16 18:19:00'
and h.closed_time < timestamp '2018-12-16 18:20:00'
everything between 6:19pm and 6:20pm (one minute time frame)
The problem presented here is not only technical but lingual. The word "between" can have several subtle differences such as driving between the gateposts (i..e hopefully that car does not hit either side and so no gatepost is included) or flying between London and Paris where both cities are included otherwise you have fallen short of the destination.
SQL standards use the latter approach for between, it is defined as inclusive of both endpoints. This is a potential problem for date/time ranges as it can lead to double-counting of endpoints. As #mathguy indicates in his excellent comment under the question the stricter approach is to avoid using between and explicitly define the range this way:
WHERE h.creation_time >= to_date('2017-01-01', 'YYYY-MM-DD')
AND h.closed_time >= to_date('2018-12-16 18:19:00', 'YYYY-MM-DD HH24:MI:SS')
AND h.closed_time < to_date('2018-12-16 18:20:00', 'YYYY-MM-DD HH24:MI:SS')
IF the closed_time column is a date data type use to_date()
IF the closed_time column is a timestamp data type use to_timestamp() instead.
I have a table that uses sysdate to assign column "insert_date" the current date and time upon inserting records into the table. I'm trying to use a query to check for records depending on the day they were inserted:
select insert_date
from integration.ol_order
where trunc(insert_date) like '%5/1/2015%'
Upon running the query, I get "ORA-01843: Not a vaild month" even though trunc(insert_date) outputs '5/1/2015'.
This occurs for the following where statements as well:
where trunc(insert_date) like '5/1/2015%'
where trunc(insert_date) = '5/1/2015'
I must be missing something simple here.
TRUNC - when applied to date - returns a date, so you should compare to a date:
where trunc(insert_date) = date '2015-01-05'
This uses a DATE literal to create a date from an ISO date string (YYYY-MM-DD).
However, this will apply TRUNC() to every row in your table, thus hurting performance. A much better solution is to compare your column to an interval:
where insert_date between date '2015-01-05' and date '2015-01-06'
UPDATE
As Wernfried pointed out, this will include '2015-01-06 00:00:00'. If that's a problem, you can either subtract a minimal timespan from the upper bound:
where insert_date between date '2015-01-05'
and date '2015-01-06' - interval '1' second
or use <= and < instead of between :
where date '2015-01-05' <= insert_date
and insert_date < date '2015-01-06'
SQL Fiddle
"LIKE" only works with character fields, not datetime fields. Also, the date format for queries is YYYY-MM-DD. To test for a date for a specific day:
insert_date BETWEEN '2015-05-01' AND '2015-05-01:23:59:59'
I'm in PostgreSQL.
I need to print all mailing with creation date strictly more that 2015-04-04. I tried the following queries:
SELECT *
FROM mailing.mailing
WHERE creation_date > '2015-04-04';
and
SELECT *
FROM mailing.mailing
WHERE creation_date >= '2015-04-04';
But they produced the same result set(including '2015-04-04'). Is it possible to write such a query without explicitly saying WHERE creation_date >= '2015-04-05';
UPD: The column's type is timestamp without time zone.
If your creation_date field is of type datetimetry comparing it to '2015-04-04 23:59:59' instead, as '2015-04-04 08:30:00' seems to be greater than '2015-04-04'.
Assuming your default date format for your database is 'YYYY-MM-DD' and creation_date field is a date type, your query will actually be converted automatically to something like:
SELECT *
FROM mailing.mailing
WHERE creation_date > to_date('2015-04-04', 'YYYY-MM-DD');
The date value you have provided represents the first second of that day, that's why you see no difference between your queries. (Your first query would exclude the first second of the day though.)
What you could do to avoid this is:
where creation_date >= to_date('2015-04-05 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
or
where date_trunc(creation_date-1) = '2015-04-04'
Currently my table has a column to store date and time. The data type of that column is timestamp without time zone. So it has values in the format '2011-09-13 11:03:44.537'.
I need to retrieve rows with respect to the date. If I use:
select * from table where mdate >= '2011-09-13 11:03:44.537'
and mdate <= '2011-09-12 11:03:44.537'
it will provide the values which are in between '2011-09-13 11:03:44.537' and '2011-09-12 11:03:44.537'.
But if I am going with:
select * from table where mdate >= '2011-09-13 00:00:00.0'
and mdate <= '2011-09-12 00:00:00.0'
without date, month and seconds, It is not displaying any rows.
How to fetch values from this table with respect to the date (only with date, ignoring hour, minutes and seconds)?
Even, the column has date with timestamp, I need to search them only with date (ignoring timestamp or making the hour, minutes and seconds to 0 such as '2011-09-13 00:00:00.0').
If you are going to cast the timestamp values of the field to date, as suggested in another answer, performance will degrade because every single value in the column needs to be cast for comparison and simple indexes cannot be used. You would have to create a special index on the expression, like so:
CREATE INDEX some_idx ON tbl (cast(mdate AS date));
In this case the query should also be simplified to:
SELECT * FROM tbl
WHERE mdate::date = '2011-09-12'::date; -- 2nd cast optional
However, as far as I can see, your problem is a simple typo / thinko in your query:
You switched upper & lower boundaries. Try:
SELECT * FROM tbl
WHERE mdate >= '2011-09-12 00:00:00.0'
AND mdate <= '2011-09-13 00:00:00.0';
Or, to simplify your syntax and be more precise:
SELECT * FROM tbl
WHERE mdate >= '2011-09-12 00:00'
AND mdate < '2011-09-13 00:00';
There is no need to spell out seconds and fractions that are 0.
You don't want to include 2011-09-13 00:00, so use < instead of <=.
Don't use BETWEEN here, for the same reason:
WHERE mdate BETWEEN '2011-09-12 00:00' AND '2011-09-13 00:00'
This would include 00:00 of the next day.
Also be aware that a column of type timestamp [without time zone] is interpreted according to your current time zone setting. The date part depends on that setting, which should generally work as expected. More details:
Ignoring time zones altogether in Rails and PostgreSQL
Just treat the timestamp as a date:
select *
from table
where mdate::date >= DATE '2011-09-12'
and mdate::date <= DATE '2011-09-13'
The expression mdate::date will cast the timestamp to a date type which will remove the time part from the value.
DATE '2011-09-13' is a (standard) DATE literal which is a bit more robust than simply writing '2011-09-13' as it isn't affected by any language settings.