Best way to handle between in two dates in postgresql on timestamp - sql

i am having date field in my table in the format of yyyy-mm-dd HH:MM:SS wanted to get records between 11-july-2020 inclusive 14-july-2020 but records are missing on 14th. Tries >= && < SYMMETRIC but non of them is working.
currently using select .... from employee where ... and created_on in between ?1 and ?2 . It is excluding record created on 14th.

I think you want:
where col >= '2020-07-11' and col < '2020-7-15'
Or, to express this using timestamps:
where col::timestamp >= '2020-07-11'::timestamp and
col::timestamp < '2020-07-14'::timestamp + interval '1 day'
Note that the higher end is one day later than 2020-07-14, so you can get all times on that day.
You can also use between as:
where col::date between '2020-07-11'::date and '2020-07-14'::date
But I discourage the use of between with date/time data types -- precisely because of the problem that you are having with the time component.

If your field has format yyyy-mm-dd HH:MM:SS it is a timestamp field not a date field. That makes a big difference in the comparison that needs to be done as #Gordon shows. If you compare a timestamp to a date(14-july-2020) the date will be turned into a timestamp with a time of 00:00:00:
select '07/14/2020'::timestamp;
timestamp
---------------------
2020-07-14 00:00:00
That means you will miss the timestamps on the 14th that fall after Midnight of 13/14th.

Related

how to select all entries having date 25-11-20 in oracle 11g?

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.

SQL - how to change the format of a current_timestamp to have 'mm ss' as zeros?

I want to check if a metric is still missing 4 hours later and return a single record if it exists. I wrote a query that checks if there were metrics in the last 4 hours. But I need to check if there is a metric for a certain hour that was expected to load 4 hours before.
-- Returns records that appeared within the last 4 hours
select * from main.basic_metrics
where metric_name = 'common_metric'
and transaction_time > current_timestamp - interval 4 hours
The problem is that transaction_timeis in the following format 2019-10-30T12:00:00.000+0000 where mm ss are always zeros. So when I check it like transaction_time = current_timestamp - interval 4 hours it returns nothing since current_timestamp contains mm ss data.
How should I format timestamp to the format similar to transaction_time - 2019-10-30T12:00:00.000+0000 ?
UPD: There was a typo, mentioned in the comments below. fixed it
That should be very simple: cast the string to timestamp with time zone:
WHERE CAST(transaction_time AS timestamp with time zone)
> current_timestamp - INTERVAL '4 hours'
Try the following:
select * from main.basic_metrics
where metric_name = 'common_metric'
and transaction_time = date_trunc('hour',current_timestamp) - interval 4 hours
This is not necessarily the best query for what you're doing, but it does solve the problem you're having. My guess is that some version of "between" or > and < would solve it, however without knowing exactly how the "transaction time" is populated, I'm could only venture guesses.
The trick in my example is to "truncate" everything after the "hours" off of the current_timestamp using date_trunc()
Note: It helps a lot to realize that timestamps are NOT formatted. Timestamps are a single long integer field that happens to get formatted on your screen so you can make sense of it. Text comparisons are nearly always the wrong way to do things, and datetime aware functions are the preferred method of doing any comparison.

How to transform Oracle DateTime to Date

For instance, I have a datetime like this '2016-04-02 00:00:00' and another like this '2016-04-02 15:10:00'. I don't care about the time-part, I want them to match just by the date-part.
I have tried with date(), to_date, datepart, nothing works.
Do it like this:
where yourField >= the start of your date range
and yourField < the day after the end of your date range
Edit starts here:
While you could use trunc, as suggested by others, bear in mind that filtering on function results tends to be slow.
Truncating the date to day should do the trick. Documentation here:
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions201.htm
For example
SELECT TRUNC(SYSDATE, 'DAY') FROM DUAL;
As others have said - there is no separate "date" data type in Oracle. A pure "date" is stored as a date with the time portion set to 00:00:00 (midnight at the beginning of the day), and TRUNC(date) will take any date and truncate the time to 00:00:00, so if you need to compare two dates you can write
where trunc(date_1) = trunc(date_2)
If your tables are very large and you need to do these comparisons often, this is not ideal, because wrapping column values within function calls (like date_1 within a TRUNC) prevents the use of an index you may have on the date_1 column. If you need to compare dates in two columns you may not have much of a choice, but if you compare to a fixed date (or something like SYSDATE) you may be better off with something like
where date_1 >= trunc(sysdate) and date_1 < trunc(sysdate) + 1
Here you are not using trunc on the column value, so if there's an index on the column, Oracle is free to use it - and trunc(sysdate) is computed only once, not for every single row. "+1" by the way means "add one day".
TO_DATE converts a string to a date; if you apply TO_DATE to a value that is already a legitimate date, you will get unexpected results because Oracle will first convert your true date to a string and then back to date again, and since these conversions require a date FORMAT for strings, and the formats Oracle assumes for conversion from date to string and from string to date may not match, .... you get the idea. As far as I know, DATE() (a FUNCTION) and DATEPART do not exist in Oracle; when you use a new language, keep Google close by and use it often.
If you input a date with no time component, for example TO_DATE('04-apr-2016, 'dd-mon-yyyy'), then the implicit time is 00:00:00 so you don't need to apply TRUNC() to it.
Good luck!

Sysdate Oracle to Run Based on Day

This is probably an easy question for most of you but how can I get this mask to run based on just the day?
If anyone knows Crystal Reports syntax, we have this and it works {PO_RECEIPTS.DATE_RECEIVED} = currentdate
However, when converting to Oracle SQL, how can I the standard: TO_CHAR
(SYSDATE, 'MM-DD-YYYY HH24:MI:SS') to become range so we can selected everything during the day, not just what matched the second in which the report was ran which it never will.
So something like Today from 00:00:00 to 23:59:59 ?
Thank you!
If PO_RECEIPTS.DATE_RECEIVED is a date column where all the times are set to midnight then you can do:
WHERE PO_RECEIPTS.DATE_RECEIVED = TRUNC(sysdate)
If the values have other times then you can use a range:
WHERE PO_RECEIPTS.DATE_RECEIVED >= TRUNC(sysdate)
AND PO_RECEIPTS.DATE_RECEIVED < TRUNC(sysdate) + 1
Truncating a date sets the time to midnight, by default, so TRUNC(sysdate) is midnight this morning. For the range you get all records equal to or later than midnight this morning, and less than midnight tomorrow - which is what TRUNC(sysdate) + 1 gives you, using normal Oracle datetime arithmetic.
You don't really want to convert it to a string with TO_CHAR(); you'd either have to convert all the column values to strings too (which is inefficient and prevents an index being used), or let the string be (implicitly) converted back to a date anyway. It's better to compare a column value with the same data type to reduce or avoid confusion.

Yesterday's date in where clase with HH:MM:SS

In my query I currently have user enter datetime.
Current query
where TableT.STARTDATETIME >= To_Date('?DATE1?','MM-DD-YYYY HH24:MI:SS')
and TableT.STARTDATETIME <= To_Date('?DATE2?','MM-DD-YYYY HH24:MI:SS')
User would enter
for Date1: 10-02-2013 00:00:00
for Date2: 10-02-2013 23:59:59
Parameter :- ?DATE? & DATE2 is just a parameter for user to enter dates.
Need
How can I made sql automatically enter yesterday's date starting from 00:00:00 to 23:59:59?
I know I can use use something like sysdate-1 but not sure.
You could use
TRUNC(TableT.STARTDATETIME) = TRUNC(sysdate-1)
for this purpose to truncate both dates to the day on both side of the check. However, for this to be efficient, you'd need a function index on TRUNC(TableT.STARTDATETIME).
Maybe better in general from a performance aspect:
TableT.STARTDATETIME >= trunc(sysdate-1) AND TableT.STARTDATETIME < trunc(sysdate);
This includes yesterday 00:00:00 (the >= ), but excludes today 00:00:00 (the <).
Warning! Keep in mind, that for TIMESTAMP columns - while tempting because of its simplicity - don't use 23:59:59 as end time, as the 1 second time slot between 23:59:59 and 00:00:00 might contain data too - and this gap will leave them out of processing...
It would be:
where TableT.STARTDATETIME >= trunc(sysdate-1) and
TableT.STARTDATETIME < trunc(sysdate)
Avoid truncating the column value itself -- although you can place an index on Trunc(TableT.STARTDATETIME) you'd need another one to support time-based queries, and it's a fine way to obscure the distribution of values from the optimiser.
Have a look here for more info on date and timestamp arithmetic, and at the Trunc(datetime, format) function for other useful ways of manipulating dates.