How to find time of day or range in TIMESTAMP column - sql

I have a list of events with begin and end timestamps in GMT UTC+0. The column is type DATE but has time as well (not designed by me).
The begin timestamp is plainly indexed
I need to find events the occur between, say, 06:00 and 22:00 Localtime which is Eastern Daylight Time UTC-4. on any day between March 31th and April 2nd.
The Only way I've found to do it is convert it TO_CHAR() then. It's also not using the index because it's using TO_CHAR function.
Here's what I go so far.
TO_CHAR(e.begin_time,'HH24:MI') >= TO_CHAR(FROM_TZ(TO_TIMESTAMP('06:00','HH24:MI'),'US/Eastern') AT TIME ZONE '+00:00','HH24:MI') AND
TO_CHAR(e.begin_time,'HH24:MI') <= TO_CHAR(FROM_TZ(TO_TIMESTAMP('22:00','HH24:MI'),'US/Eastern') AT TIME ZONE '+00:00','HH24:MI') AND
TO_CHAR(e.begin_time,'DDMMYYYY HH24:MI') >= TO_CHAR(FROM_TZ(TO_TIMESTAMP('Mar-31-2012 00:00','MON-DD-YYYY HH24:MI'),'US/Eastern') AT TIME ZONE '+00:00','DDMMYYYY HH24:MI') AND
TO_CHAR(e.begin_time,'DDMMYYYY HH24:MI') <= TO_CHAR(FROM_TZ(TO_TIMESTAMP('Apr-2-2012 23:59','MON-DD-YYYY HH24:MI'),'US/Eastern') AT TIME ZONE '+00:00','DDMMYYYY HH24:MI')
Thanks in advance,
Dan

The performance of the following might not be what's wanted, but if you cast the DATE value to a TIMESTAMP you can use the EXTRACT function in a manner similar to:
SELECT *
FROM your_table e
WHERE e.BEGIN_TIME BETWEEN TO_DATE('31-MAR-2012 00:00:00',
'DD-MON-YYYY HH24:MI:SS')
AND TO_DATE('02-APR-2012 23:59:59',
'DD-MON-YYYY HH24:MI:SS') AND
EXTRACT(HOUR FROM CAST(e.BEGIN_TIME AS TIMESTAMP)) BETWEEN 6 AND 22
Share and enjoy.

When trying to grab data based on a portion of a date field, of course the index will not be used. there just ain't any workaround to that. You could look into adding a function-based index, however, to index on the minutes of the day in EST. Or, perhaps, add a new column to hold minutes_est, have it populated by an insert/update trigger and then base your query on that.
If this is a regularly used query, and the performance of a full table scan isn't cutting it, then yes - I think this is one of those times where you might need to do some redesign based on your needs for this.

Related

How to use TO_DATE to update a DATE field in SQL to a PM time

What I need to do is pretty simple.
I just need to update a DATE field in SQL to a PM time.
Only thing is, if I use the TO_DATE function to update to an AM time, no problem...
TO_DATE('2021-09-30 11:00:00', 'YYYY-MM-DD HH:MI:SS')
However if I try to do the same thing to set to a PM time using military time...
TO_DATE('2021-09-30 23:00:00', 'YYYY-MM-DD HH:MI:SS')
It says that the hour has to be between 1 and 12.
Any suggestions?
Thanks
According to the Oracle documentation, in order to convert a time in 24 hour format, you need to use HH24. When you use just HH, Oracle assumes the time to be in AM/PM format, i.e. that the number must be between 1 and 12.
So you need to change your code to the following
TO_DATE('2021-09-30 23:00:00', 'YYYY-MM-DD HH24:MI:SS')
Refer to this db<>fiddle

What should be the outcome of TRUNC('02-MAY-14','HH24')?

I found a bizarre snippet which is confusing me so I thought I'll ask the experts.
Let assume a tableA got following columns with data:
"START_TIME":1399075198
"END_TIME":1399075200
"START_DATE":"02-MAY-14"
"END_DATE":"03-MAY-14"
Now query 1:
SELECT MIN(start_date) INTO sdate FROM tableA;
query 2:
SELECT TRUNC(sdate, 'HH24') + INTERVAL '30' MINUTE from dual;
So if start-date = '02-MAY-14', how would that truncate to 'HH24'?
The expression:
TRUNC(sdate, 'HH24')
cuts off everything from a date that is smaller than an hour, i.e. the minutes and seconds. For the specific date:
TRUNC('02-MAY-14','HH24')
it returns the date unchanged. It only makes sense if the Oracle date contains a time component.
Possibly, your SQL tool (SQL Developer, TOAD etc.) is configured to not display the time part of Oracle dates. So the original date might in fact be 02-MAY-14 09:03:25. Then it would return:
02-MAY-14 09:00:00
You mention the columns START_TIME and END_TIME but don't use them in the SQL queries. What are they for?
As start_date does not have a time part in your example, TRUNC is superfluous here. If however it had a timepart, if for example start_time had been added to start_date before, then TRUNC would remove minutes, seconds and microseconds, only keeping the date and hour because of 'HH24' which means "truncate datetime down to full hour".
In Oracle the date datatype inherently store the time as well.
Try executing the below query. It should clear things up a bit:
SELECT TO_CHAR(SYSDATE,'DD-MON-YYYY HH:MI:SS'), TO_CHAR(TRUNC(SYSDATE,'HH24'),'DD-MON-YYYY HH:MI:SS') FROM DUAL;

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.

How to get the date and time from timestamp in PostgreSQL select query?

How to get the date and time only up to minutes, not seconds, from timestamp in PostgreSQL. I need date as well as time.
For example:
2000-12-16 12:21:13-05
From this I need
2000-12-16 12:21 (no seconds and milliseconds only date and time in hours and minutes)
From a timestamp with time zone field, say update_time, how do I get date as well as time like above using PostgreSQL select query.
Please help me.
There are plenty of date-time functions available with postgresql:
See the list here
http://www.postgresql.org/docs/9.1/static/functions-datetime.html
e.g.
SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 16
For formatting you can use these:
http://www.postgresql.org/docs/9.1/static/functions-formatting.html
e.g.
select to_char(current_timestamp, 'YYYY-MM-DD HH24:MI') ...
To get the date from a timestamp (or timestamptz) a simple cast is fastest:
SELECT now()::date
You get the date according to your local time zone either way.
If you want text in a certain format, go with to_char() like #davek provided.
If you want to truncate (round down) the value of a timestamp to a unit of time, use date_trunc():
SELECT date_trunc('minute', now());
This should be enough:
select now()::date, now()::time
, pg_typeof(now()), pg_typeof(now()::date), pg_typeof(now()::time)

Is a date in Oracle-SQL without a time-value always 00:00:00?

Heyho,
I need to grab some datas from actions which been done from date A 00:00:00 and date B 00:00:00 (in this case
Date A: 16.07.2010
Date B: 20.07.2010)
so i wrote this select-statement:
Select avg(cnt),fext from (
Select
to_char(mytable.dateadded, 'DD.MM.YYYY') dateadded,
fext,
count(id) cnt
from mytable
where dateadded between
to_date('16.07.2010', 'dd,MM,YYYY') and
to_date('20.07.2010', 'dd,MM,YYYY')
group by
to_char(mytable.dateadded, 'DD.MM.YYYY'),
fext)
group by fext;
The original (and working) statement had:
to_date('16.07.2010 00:00:00', 'dd,MM,YYYY HH24:Mi:SS') and
to_date('20.07.2010 00:00:00', 'dd,MM,YYYY HH24:Mi:SS')
so the question is: does the
to_date('16.07.2010', 'dd,MM,YYYY') and
to_date('20.07.2010', 'dd,MM,YYYY')
already set the time to date A and B to 00:00:00?
Greetz
If you does not specify time part of date it will be 00:00:00.
If you worry about time part you always can truncate time part:
Trunc(to_date('16.07.2010', 'dd.MM.YYYY')) and
Trunc(to_date('20.07.2010', 'dd.MM.YYYY'))
The easiest way is to use ANSI date literals, which doesn't allow time to be specified and is thus with a 00:00:00 time part internally:
dateadded between date '2010-07-16' and date '2010-07-20'
Your expressions look odd, as your date string has dots as the time component separator, but your date format has commas. Oracle accepts it though:
rwijk#XE> select to_date('16.07.2010', 'dd,MM,YYYY') from dual;
TO_DATE('16.07.2010
-------------------
16-07-2010 00:00:00
1 row selected.
I'd use the ANSI date literal for its simplicity.
Regards,
Rob.
this query will returns you one row which answers your question i think :
SELECT TO_DATE('16.07.2010 00:00:00', 'dd,MM,YYYY HH24:Mi:SS'),
TO_DATE('16.07.2010', 'dd,MM,YYYY')
FROM dual
WHERE to_date('16.07.2010 00:00:00', 'dd,MM,YYYY HH24:Mi:SS') = to_date('16.07.2010', 'dd,MM,YYYY')
This is one thing that SQL is consistent about - if you don't provide a time portion on a DATE data type that includes a time portion (IE Oracle, PostgreSQL while MySQL and SQL Server explicitly call it DATETIME), then the time portion is defaulting to exactly midnight of that date - 00:00:00. And being midnight, that means the start of the date - if you want to include the entire date in a date comparison, the value's time portion needs to be 23:49:49 -- a second to midnight.
23:59:59 is a second to midnight. Essentially midnight is defined as the start of a day: 00:00:00. Then the seconds clock up to the end of the day.