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 :)
Related
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.
I'm new to SQL and was wondering if you could help me create a query that compares the time difference in Days, Hours, Minutes.
For example,
Start time 1 = 13/01/2016, 16:00
End time 1 = 14/01/2016, 18:00
So the time difference should be 1 day and 2 hours right?
Another example.
Start time 2 = 20/10/2016, 12:00
End time 2 = 20/10/2016, 16:00
So the
time difference is just 2 hours.
The reason I need this query is to create a report based on the difference in time between a start time and a finish time of a task.
watch out for problems with DATEDIFF that ignores fractions of days etc
DECLARE #Starttime DATETIME = '20160113 16:00';
DECLARE #Endtime DATETIME ='20160114 15:59';
--calculate difference in seconds then use integer divides and MODULUS to extract days, hours, minutes
;WITH DIFF_SECS AS (SELECT CAST(DATEDIFF(second,#Starttime,#Endtime) AS BIGINT) AS SD)
SELECT SD / (24 * 3600) as NoDays,
(SD % (24 * 3600)) / 3600 as NoHours,
(SD % 3600) / 60 AS NoMinutes
FROM DIFF_SECS;
if you aren't using microsoft SQL - then the formulae are possible still useful
if X = 'difference between times in seconds'
then whole days = X / (24 * 3600) where the divide is an integer divide (always rounds down)
In Oracle I would do it like that:
-- this is only to create some data
WITH MyRows AS (
SELECT to_date('2000/11/30 12:59', 'YYYY/MM/DD HH24:MI') BEGINNING, to_date('2000/11/30 14:01', 'YYYY/MM/DD HH24:MI') ENDING FROM DUAL UNION
SELECT to_date('2000/12/01 12:59', 'YYYY/MM/DD HH24:MI') , to_date('2000/12/02 00:01', 'YYYY/MM/DD HH24:MI') FROM DUAL UNION
SELECT to_date('2000/12/30 12:59', 'YYYY/MM/DD HH24:MI') , to_date('2000/12/31 14:01', 'YYYY/MM/DD HH24:MI') FROM DUAL UNION
SELECT to_date('2000/12/31 12:59', 'YYYY/MM/DD HH24:MI') , to_date('2001/01/01 04:01', 'YYYY/MM/DD HH24:MI') FROM DUAL
)
-- this is the select
SELECT
BEGINNING,
ENDING,
ENDING-BEGINNING IN_DAYS,
(ENDING-BEGINNING)*24 IN_HOURS,
(ENDING-BEGINNING)*24*3600 IN_SECONDS,
case
when (ENDING-BEGINNING)*24*60 >= 3 then round(((ENDING-BEGINNING)*24*60-3)*2)
else 0
end Total_cost_in_hamburgers
FROM MyRows
;
timedifferences are days and if you want to calculate with it (f.e. after 3 minutes every minute costs 2 hamburgers) it is better to calculate that way
I am just trying to add 1 hour to a value, it is kind of complicated on where and why i am doing this but basically i just need to query something like this
select DATE_ADD(hh,1,'2014-10-15 03:30:00 pm') from dual
I keep reading old articles that say to use dateAdd or date_add but I keep getting invalid identifier errors.
select sysdate + 1/24 from dual;
sysdate is a function without arguments which returns DATE type
+ 1/24 adds 1 hour to a date
select to_char(to_date('2014-10-15 03:30:00 pm', 'YYYY-MM-DD HH:MI:SS pm') + 1/24, 'YYYY-MM-DD HH:MI:SS pm') from dual;
Use an interval:
select some_date_column + interval '1' hour
from your_table;
You can use INTERVAL type or just add calculated number value - "1" is equal "1 day".
first way:
select date_column + INTERVAL '0 01:00:00' DAY TO SECOND from dual;
second way:
select date_column + 1/24 from dual;
First way is more convenient when you need to add a complicated value - for example, "1 day 3 hours 25 minutes 49 seconds".
See also: http://www.oracle-base.com/articles/misc/oracle-dates-timestamps-and-intervals.php
Also you have to remember that oracle have two interval types - DAY TO SECOND and YEAR TO MONTH.
As for me, one interval type would be better, but I hope people in oracle knows, what they do ;)
Old way:
SELECT DATE_COLUMN + 1 is adding a day
SELECT DATE_COLUMN + N /24 to add hour(s) - N being number of hours
SELECT DATE_COLUMN + N /1440 to add minute(s) - N being number of minutes
SELECT DATE_COLUMN + N /86400 to add second(s) - N being number of seconds
Using INTERVAL:
SELECT DATE_COLUMN + INTERVAL 'N' HOUR or MINUTE or SECOND - N being a number of hours or minutes or seconds.
To add/subtract from a DATE, you have 2 options :
Method #1 :
The easiest way is to use + and - to add/subtract days, hours, minutes, seconds, etc.. from a DATE, and ADD_MONTHS() function to add/subtract months and years from a DATE. Why ? That's because from days, you can get hours and any smaller unit (1 hour = 1/24 days), (1 minute = 1/1440 days), etc... But you cannot get months and years, as that depends on the month and year themselves, hence ADD_MONTHS() and no add_years(), because from months, you can get years (1 year = 12 months).
Let's try them :
SELECT TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints current date: 19-OCT-2019 20:42:02
SELECT TO_CHAR((SYSDATE + 1/24), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date + 1 hour: 19-OCT-2019 21:42:02
SELECT TO_CHAR((SYSDATE + 1/1440), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date + 1 minute: 19-OCT-2019 20:43:02
SELECT TO_CHAR((SYSDATE + 1/86400), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date + 1 second: 19-OCT-2019 20:42:03
-- Same goes for subtraction.
SELECT SYSDATE FROM dual; -- prints current date: 19-OCT-19
SELECT ADD_MONTHS(SYSDATE, 1) FROM dual; -- prints date + 1 month: 19-NOV-19
SELECT ADD_MONTHS(SYSDATE, 12) FROM dual; -- prints date + 1 year: 19-OCT-20
SELECT ADD_MONTHS(SYSDATE, -3) FROM dual; -- prints date - 3 months: 19-JUL-19
Method #2 : Using INTERVALs, you can or subtract an interval (duration) from a date easily. More than that, you can combine to add or subtract multiple units at once (e.g 5 hours and 6 minutes, etc..)
Examples :
SELECT TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints current date: 19-OCT-2019 21:34:15
SELECT TO_CHAR((SYSDATE + INTERVAL '1' HOUR), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date + 1 hour: 19-OCT-2019 22:34:15
SELECT TO_CHAR((SYSDATE + INTERVAL '1' MINUTE), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date + 1 minute: 19-OCT-2019 21:35:15
SELECT TO_CHAR((SYSDATE + INTERVAL '1' SECOND), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date + 1 second: 19-OCT-2019 21:34:16
SELECT TO_CHAR((SYSDATE + INTERVAL '01:05:00' HOUR TO SECOND), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date + 1 hour and 5 minutes: 19-OCT-2019 22:39:15
SELECT TO_CHAR((SYSDATE + INTERVAL '3 01' DAY TO HOUR), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date + 3 days and 1 hour: 22-OCT-2019 22:34:15
SELECT TO_CHAR((SYSDATE - INTERVAL '10-3' YEAR TO MONTH), 'DD-MON-YYYY HH24:MI:SS') FROM dual; -- prints date - 10 years and 3 months: 19-JUL-2009 21:34:15
The calculation is simple
if you want to add 1 hour in the date .
every day have 24 hour , you can add .
select sysdate + 1/24 from dual;
if you want 1 day to add
select sysdate + 24/24 from dual;
or
select sysdate + 1 from dual;
same as for 2, 3 , 4 day
For static date you have the answer below.
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.
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 ;