Why is my date conversion so off? - sql

I run these two statements in sql and the dates are two days apart. This ruins my query. Why are they not both 10/13/2015?
select sysdate from dual
-- 10/13/2015 5:09:43 PM
select trunc(sysdate, 'DAY') from dual
-- 10/11/2015

trunc 'DAY' returns the starting day of the week. Use 'DDD', 'DD' or 'J' to truncate to a day.

I assume you want to truncate the time. So you can just remove the second parameter if you want to truncate the time to midnight.
SELECT to_char(SYSDATE,'mm/dd/yyyy hh24:mi:ss') FROM dual;
/
SELECT to_char(trunc(SYSDATE),'mm/dd/yyyy hh24:mi:ss') FROM dual;
Output:
TO_CHAR(SYSDATE,'MM/DD/YYYYHH24:MI:SS')
---------------------------------------
10/14/2015 07:35:24
TO_CHAR(TRUNC(SYSDATE),'MM/DD/YYYYHH24:MI:SS')
----------------------------------------------
10/14/2015 00:00:00

Related

Column based on time range in Oracle

I have a sales table with created datetime, my business hours are from 9 AM to 2 AM in the night on the following day. I am trying to convert the dates into my business date.
01/08/22 09:39:12.000000000 AM +04:00
Lets say I have a sale at 1 AM, this sale has to be considered in the previous day.
Any function that can help me solve this issue would be appreciated
It might be a bit of an overkill, but you could just use EXTRACT:
WITH dat AS
(
SELECT to_date('01/08/22 09:39:12','DD/MM/YY HH24:MI:SS') AS t_stmp FROM dual UNION ALL
SELECT to_date('02/08/22 01:03:15','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 08:27:33','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 14:11:51','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 02:01:15','DD/MM/YY HH24:MI:SS') FROM dual
)
SELECT CASE WHEN EXTRACT(HOUR FROM CAST(t_stmp AS TIMESTAMP)) BETWEEN 2 AND 8 THEN -1
ELSE 0
END + TRUNC(t_stmp,'DD') AS business_date
FROM dat;
business_date
01.08.2022
02.08.2022
01.08.2022
02.08.2022
01.08.2022
It looks like you just need to make a 2 hour shift to get your sales in the right date. You can add or substract hours from DATE/DATETIME/TIMESTAMP data type. If your column is TIMESTAMP then it would be like this:
-- when selecting data for date of sales
SELECT TRUNC(your_column_name - INTERVAL '2' HOUR, 'dd') "SALE_DATE"
-- And/Or
WHERE TRUNC(your_column_name - INTERVAL '2' HOUR, 'dd') = :DATE_OF_SALES
-- TRUNC function always returns DATE datatype
--
-- The opposite conversion would be
CAST(your_datetime_column + INTERVAL '2' HOUR as TIMESTAMP) ...
Here is the small sample with result:
SELECT
to_char(SYSDATE, 'dd.mm.yyyy hh24:mi:ss') "DATETIME",
to_char(SYSDATE - INTERVAL '2' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_MINUS_2H",
to_char(SYSDATE + INTERVAL '2' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_PLUS_2H",
to_char(SYSDATE - INTERVAL '10' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_MINUS_10H"
FROM
DUAL
--
-- R e s u l t
--
-- DATETIME DATETIME_MINUS_2H DATETIME_PLUS_2H DATETIME_MINUS_10H
-- ------------------- ------------------- ------------------- -------------------
-- 07.08.2022 09:58:38 07.08.2022 07:58:38 07.08.2022 11:58:38 06.08.2022 23:58:38
The last column now has the date from day before.

Oracle query on time (and not date)

How can you query on just the time portion of an Orace date field. Ie:
select * from mytable
where
date_column < '05:30:00'
Want the query to return any rows where the time represented by date_column is less than 5:30 regardless of the date.
You can try like this:
select * from mytable
where
to_char( date_column, 'HH24:MI:SS' ) < '05:30:00'
You can see how far the date is from midnight, and filter on that:
select * from mytable
where date_column - trunc(date_column) < 5.5/24
The date_column - trunc(date_column) calculation will give you a fraction of a day, as is normal for date arithmetic. The 5.5/24 is the fraction of the day represented by the time at 05:30; 5.5 hours out of 24 hours.
If the column was a timestamp instead of a date you'd see an interval data type as the result of the subtraction. You can use an interval literal anyway if you prefer or find it easier to understand than 5.5/24 (or have more complicated times to compare, which are harder to express as a fraction):
select * from mytable
where date_column < trunc(date_column) + interval '0 05:30:00' day to second;
This way round you're comparing the date in your column with the truncated date (i.e. midnight on that day) with 5 hours 30 minutes added to it, which is 05:30 the same day.
Quick demo with simple data in a CTE, and a third very slight variant, but they all get the same result:
with mytable (date_column) as (
select to_date('2016-04-15 05:29:29', 'YYYY-MM-DD HH24:MI:SS') from dual
union all select to_date('2016-04-14 05:29:29', 'YYYY-MM-DD HH24:MI:SS') from dual
union all select to_date('2016-04-15 05:30:30', 'YYYY-MM-DD HH24:MI:SS') from dual
)
select * from mytable
where date_column < trunc(date_column) + 5.5/24;
DATE_COLUMN
-------------------
2016-04-15 05:29:29
2016-04-14 05:29:29
Note though that any manipulation of the column like this will prevent an index being used. If you have to do this regularly it might be worth adding a virtual column/index which does that calculation.
You need to cast the time back to date, otherwise you're simply doing string comparison.
Oracle doesn't really have a clever way of doing this. Simplest to cast both dates to the same day and do the comparison.
I.e.
select *
from mytable
where to_date ('01.01.2000 ' || to_char (date_column, 'hh24:mi:ss'), 'dd.mm.yyyy hh24:mi:ss') <
to_date ('01.01.2000' || '05:30:00', 'dd.mm.yyyy hh24:mi:ss')

Select Dates where time is less or equal to '12:00' Oracle

I require a query that selects rows where the time is less or equal to 12:00
I had something like this in mind:
SELECT daterow FROM datecolumn WHERE daterow <= TO_DATE('12:00, HH24:MI')
However i get an error:
ORA-01843: not a valid month
How would i go about to get all rows that have a time less than 12:00 mid-day?
Try this,
SELECT daterow FROM datecolumn WHERE daterow <= TO_DATE('12:00', 'HH24:MI');
Try This:
SELECT daterow FROM datecolumn
WHERE TO_DATE(daterow,'HH24:MI') <= TO_DATE('12:00', 'HH24:MI');
In order to select all rows where time portion of the daterow column value is less than or equal to mid-day 12:00 you can use to_char() function to extract hour and minutes and to_number() to convert it to a number for further comparison:
-- sample of data. Just for the sake of demonstration
SQL> with t1(col) as(
2 select sysdate - to_dsinterval('P0DT3H') from dual union all
3 select sysdate - to_dsinterval('P0DT2H') from dual union all
4 select sysdate - to_dsinterval('P0DT1H') from dual union all
5 select sysdate + to_dsinterval('P0DT3H') from dual union all
6 select sysdate + to_dsinterval('-P2DT0H') from dual
7 )
8 select to_char(col, 'dd.mm.yyyy hh24:mi:ss') as res
9 from t1 t
10 where to_number(to_char(col, 'hh24mi')) <= 1200
11 ;
Result:
RES
-------------------
26.08.2013 08:10:59
26.08.2013 09:10:59
26.08.2013 10:10:59
24.08.2013 11:10:59
Sorry, but <= TO_DATE('12:00', 'HH24:MI') does not work. It does not extract the hour and minute from each date and compares it to 12:00. Instead it constructs the date representing high noon on the fisrt of the current month and compares each date to this date.
If you want to extract something from a date, use the extract function.
Attention: When using extract on a date, and want to extract hours, minutes or seconds, you have first to convert the date to a timestamp.
Example:
SELECT
extract(hour FROM cast(A AS TIMESTAMP)) AS h,
extract(MINUTE FROM cast(A AS TIMESTAMP)) AS m
FROM
DEMO
;
You can find a complete example on sqlfiddle. The example also shows that the to_date method doesn't work.

Oracle Timestamp Conversion with Dates

Assuming this has a simple solution, but I can't find it.
I'm trying to do some logic on a DATE field in Oracle. My desire is to take a DATE field and subtract X hours from it.
For instance: SELECT A.MyDATE - 100 Hours from dual;
however, I need a result in a timestamp format 'YYYY-MM-DD hh:mm'.
I've tried CAST(A.MyDATE as TIMESTAMP) - NUMTODSINTERVAL(100/24,'day') however it didn't work.
I found out that the issue is that the MyDATE field when cast to a timestamp still contained some residual time elements. How can I reset these??
Thanks!
You can just do this with subtraction:
select a.MyDate - 100.0/24
To convert to varchar:
select to_char(a.MyDate - 100.0/24, 'YYYY-MM-DD')
And, if you want to get rid of that pesky time on the date:
select trunc(a.MyDate - 100.0/24) as JustTheDate
The formats and dates in my example can be changed to any other formats and dates:
SELECT To_Timestamp(To_Char(Sysdate - INTERVAL '100' HOUR, 'MM/DD/YYYY HH24:MI'), 'MM/DD/YYYY HH24:MI')
FROM dual
/
Output:
2/4/2013 10:18:00.000000000 AM
To remove time element add Trunc() to any of your dates...:
SELECT Trunc(To_Timestamp(To_Char(Sysdate - INTERVAL '100' HOUR, 'MM/DD/YYYY HH24:MI'), 'MM/DD/YYYY HH24:MI'))
FROM dual
/
Output: 2/4/2013
Conversion/Casting - when using other dates in place of sysdate then add formats as in my other examples:
SELECT CAST(SYSDATE AS TIMESTAMP) - INTERVAL '100' HOUR FROM dual
/
Output: 2/4/2013 10:26:35.000000000 AM
SELECT start_date tstamp_to_date, CAST(start_date AS timestamp) date_to_tstamp FROM
(
SELECT to_date(to_char(to_timestamp ('2013-02-07 10:07:47.000' , 'YYYY-MM-DD HH24:MI:SS.FF'),'DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS') start_date
FROM dual
)
/
Output:
tstamp_to_date date_to_tstamp
-------------------------------------------------------
2/7/2013 10:07:47 AM 2/7/2013 10:07:47.000000 AM
In Oracle, a DATE always has a day and a time component. Depending on the tool you are using and your session's NLS_DATE_FORMAT, it is entirely possible that the tool may not display the time component when you look at the data. But that is simply a display question, it has no impact on the actual data.
If you want to subtract 100 hours from midnight on the day that MyDate represents
SELECT TRUNC(MyDate) - interval '100' hour
FROM dual
This will return a DATE. If you want to return a string in a particular format
SELECT TO_CHAR( TRUNC(MyDate) - interval '100' hour, 'YYYY-MM-DD hh:mi am' )
FROM dual
Note that I'm assuming that there was a typo in your question. I assume that you want to display the minutes after the hour (mi) rather than the month (mm).
I am trying to fetch the records which is older than 30 days (from Mod_date) and I am using the below query and it is returning all the data and I want only 30 days old data.
Sample :- Mod_date 03-NOV-12 12.00.00.000000000 AM
Query :-
select Mod_date from fil_cnfact where Mod_date <= sysdate -30 order by Mod_date asc ;

Increment Oracle time in varchar field by a certain amount?

We have times stored in an Oracle varchar(5) field.
Times stored using HH24:MI (ie: 22:30, 10:15).
How can we run a query that will increase or decrease these times by a certain amount? Ie: increase by one hour or decrease by 45 minutes.
you could use the built-in date (and interval -- thanks Alex for the link) calculation:
to_char(to_date(:x, 'hh24:mi') + INTERVAL :y MINUTE,'hh24:mi')
for instance:
SQL> WITH my_data AS (
2 SELECT '12:15' t FROM dual
3 UNION ALL SELECT '10:30' FROM dual
4 )
5 SELECT t,
6 to_char(to_date(t, 'hh24:mi') + INTERVAL '15' MINUTE,'hh24:mi')"t+15"
7 FROM my_data;
T t+15
----- -----
12:15 12:30
10:30 10:45
The functions to convert from/to date and char are TO_DATE() and TO_CHAR():
SELECT
TO_DATE('31/12/2001 23:55:00', 'DD/MM/YYYY HH24:MI:SS') AS "DATE",
TO_CHAR(CURRENT_TIMESTAMP, 'DD/MM/YYYY HH24:MI:SS') AS "CHAR"
FROM DUAL
So you can do:
SELECT
TO_DATE('23:45', 'HH24:MI'),
TO_DATE('23:45', 'HH24:MI') + INTERVAL '45' MINUTE,
TO_CHAR(TO_DATE('23:45', 'HH24:MI') + interval '45' MINUTE, 'HH24:MI')
FROM DUAL
There're possibly other better ways to do it (I'm not sure this will work as expected if ran when DST is about to start) but I'm still learning :)