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

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;

Related

V$TRANSACTION table to find the duration of transactions

How to find the names of transactions that have been active for more than 30 minutes from the current time using the START_TIME column of V$TRANSACTION table in Oracle?
We can do arithmetic with dates in Oracle. Sysdate is the current datetime. There are 48 half-hours in a day. So:
select *
from V$TRANSACTION
where to_date(start_time, 'mm/dd/yyyy hh24:mi:ss') <= sysdate - (1/48)
Hmmm, it seems slightly odd that V$TRANSACTION.start_time uses a different format mask from sysdate. Anyway, you can avoid the ORA-01843 error with an explicit date conversion.

Epoch date in the form 'YYYY-MM-DD"T"HH24:MI:SS"Z"'

I am new to SQL and have run into a problem. I want to have the epoch date i.e. 1970-01-01T00:00:00Z in this mentioned format.
I cannot use it as a constant (i.e. '1970-01-01T00:00:00Z') for programming reasons. I need a statement that gives this as an output. I have used this:
select to_char(TRUNC(add_months(sysdate,-555),'MM'), 'YYYY-MM-DD"T"HH24:MI:SS"Z"') from dual;
But the only problem with this statement is it will not give me the date I want next month i.e. it is month specific it will only work for April 2016. But I need a the date to always remain 1970-01-01T00:00:00Z.
Thanks in advance for the help.
PS: I am using Oracle SQL Developer (if that matters).
You can just do:
select '1970-01-01T00:00:00Z' from dual;
Or if you want to have it processed for some reason, which seems like pointless overhead:
select to_char(date '1970-01-01', 'YYYY-MM-DD"T"HH24:MI:SS"Z"') from dual;
Either will give you the string you want. But it is a string, not a date. If you want it as a proper data type (which I don't think you do, but maybe this is for comparison) it needs to be a timestamp with time zone, which you can get with:
select timestamp '1970-01-01 00:00:00 UTC' from dual;
Well this might not be the most elegent way but it is a way that will work:
select regexp_substr('1970-01-01T00:00:00Z','^....................',1,1) from dual;

Timestamp data type query in Oracle

I have a table called CYCLING_ACCIDENTS_2 containing a TIMESTAMP(6) column called ACC_DATE_TIME , this is an example of how the date is stored 31-MAY-12 16.45.00.000000, I would like to know how I can query just the time in such a date format so that I can have a time interval for all years I have (2005-2012) but just restricted to certain times in the day. I tried many functions but all I've got so far are syntax errors, I tried to search on the web but I can' t see anything appropriate to my case. Could anyone help?
Thanks!
First of all, a timestamp is a number, not a string. So the date is displayed by default as 31-MAY-12 16.45.00.000000, but it is actually the amount of microseconds since 1970 I believe.
If you want to select just the time part use to_char()
select to_char(acc_date_time, 'hh24:mi') time
, count(*) occurences
from cycling_accidents_2
group by to_char(acc_date_time, 'hh24:mi')
edit: I think this second query actually answers your question:
select *
from cycling_accidents_2 ca
where to_char(ca.acc_date_time, 'hh24:mi') between '10:00' and '18:00'
and ca.acc_date_time >= to_timestamp('01-01-2005', 'dd-mm-yyyy')
and ca.acc_date_time < to_timestamp('01-01-2013', 'dd-mm-yyyy')
SELECT * FROM CYCLING_ACCIDENTS_2 WHERE
(EXTRACT(YEAR FROM ACC_DATE_TIME) BETWEEN 2005 AND 2012)
AND
(EXTRACT(HOUR FROM ACC_DATE_TIME) BETWEEN 10 AND 18)

Compare date + time with timestamp

I have a table with two temporal columns. First (name is DATE) is storing the date (not including the time part) and therefor the datatype is DATE. Second column (name is TIME) is for storing the time in seconds and therefor the datatype is NUMBER.
I need to compare this two dates with a timestamp from another table. How can I calculate the date of the two columns (DATE and TIME) and compare to the timestamp of the other table?
I have tried to calculate the hours out of the time column and add it to the date column, but the output seems not correct:
SELECT to_date(date + (time/3600), 'dd-mm-yy hh24:mi:ss') FROM mytable;
The output is just the date, but not the time component.
You can use the INTERVAL DAY TO SECOND type:
SELECT your_date + NUMTODSINTERVAL(your_time_in_seconds, 'SECOND') FROM dual;
Example:
SELECT TRUNC(SYSDATE) + NUMTODSINTERVAL(39687, 'SECOND') FROM dual;
The calculated date with time is: 10-11-2013 11:01:27
This is a better idea than dividing your value by 3600 in my opinion, as you have an interval in seconds, so it feels natural to use an interval to represent your time, which can then be easily added to a column of DATE datatype.
Oracle Interval in Documentation
NUMTODSINTERVAL Function in documentation
date + (time/3600) is already a DATE, so you don't need to do to_date(). It does have the time part you added though, you just aren't displaying it. If you want to output that as a string in the format you've shown, use to_char() instead:
SELECT to_char(date + (time/3600), 'dd-mm-yy hh24:mi:ss') FROM mytable;
... except that if time is actually in seconds, you need to divide by 86400 (24x60x60), not 3600. At the moment you're relying on your client's default date format, probably NLS_DATE_FORMAT, which doesn't include the time portion from what you've said. That doesn't mean the time isn't there, it just isn't displayed.
But that is just for display. Leave it as a date, by just adding the two values, when comparing against you timestamp, e.g.
WHERE date + (time/86400) < systimestamp
Try like this,
SELECT TO_DATE('11/11/2013','dd/mm/yyyy') + 3600/60/60/24 FROM DUAL;
Your query,
SELECT date + time/60/60/24 FROM mytable;
try using to_timestamp instead of to_date

How to find time of day or range in TIMESTAMP column

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.