Timestamp + Numeric hours in Oracle SQL - sql

In my Input tables I am trying to add hours (NUMERIC) to a timestamp
time_of_Day
2020-10-01 22:15:00
2020-11-01 15:04:00
hours_to_add
3
4
Expected result
2020-10-02 01:15:00
2020-11-01 19:04:00
I tried the following method but I get an error: invalid input syntax for type interval: "hours_to_add"
SELECT
time_of_Day+ interval 'hours_to_add' hour
from your_table;

You can just do:
select time_of_Day + hours_to_add/24 from your_table;
This produces a result of date datatype.
If you wanted interval arithmetics (and have a result of timestamp datatype):
select time_of_day + hours_to_add * interval '1' hour from your_table
Demo on DB Fiddle:
with t as (
select timestamp '2020-10-01 22:15:00' time_of_Day , 3 hours_to_add from dual
union all select timestamp '2020-11-01 15:04:00', 4 from dual
)
select
t.*,
time_of_day + hours_to_add/24 as_date,
time_of_day + hours_to_add * interval '1' hour as_timestamp
from t
TIME_OF_DAY | HOURS_TO_ADD | AS_DATE | AS_TIMESTAMP
:------------------ | -----------: | :------------------ | :------------------
2020-10-01 22:15:00 | 3 | 2020-10-02 01:15:00 | 2020-10-02 01:15:00
2020-11-01 15:04:00 | 4 | 2020-11-01 19:04:00 | 2020-11-01 19:04:00

Multiple the value with a fixed interval:
select time_of_day + interval '1' hour * hours_to_add
from the_table;
Online demo

The TIMESTAMP datatype is an extension of the DATE datatype. It stores year, month, day, hour, minute, and second values. It also stores fractional seconds, which are not stored by the DATE datatype.
So, if you don't want to display the fractional seconds, then use proper format mask using TO_CHAR to display what you want.
Here is a working demo:
with your_table as
(
select timestamp '2020-10-01 22:15:00' time_of_Day , 3 hrs from dual
union all
select timestamp '2020-11-01 15:04:00', 4 from dual
)
select time_of_day,
to_char(time_of_day + interval '1' hour * hrs, 'YYYY-MM-DD HH24:MI:SS') new_time
from your_table;
TIME_OF_DAY NEW_TIME
------------------------------ -------------------
01-10-20 10:15:00.000000000 PM 2020-10-02 01:15:00
01-11-20 3:04:00.000000000 PM 2020-11-01 19:04:00
The timestamp will still have the fractional seconds stored as 02-10-20 1:15:00.000000000 AM.

Related

How to convert unix timestamp and aggregate min and max date in Oracle SQL Developer?

I have table in Oracle SQL like below:
ID | date | place
-----------------------------
123 | 1610295784376 | OBJ_1
444 | 1748596758291 | OBJ_1
567 | 8391749204754 | OBJ_2
888 | 1747264526789 | OBJ_3
ID - ID of client
date - date in Unix timestamp in UTC
place - place of contact with client
And I need to aggregate above date to achieve results as below, so I need to:
convert unix timestamp in UTC from column "date" to normal date as below
calculate min and max date for each values from column "place"
min_date
max_date
distinct_place
2022-01-05
2022-02-15
OBJ_1
2022-02-10
2022-03-20
OBJ_2
2021-10-15
2021-11-21
OBJ_3
You can use:
SELECT TIMESTAMP '1970-01-01 00:00:00 UTC'
+ MIN(date_column) * INTERVAL '0.001' SECOND(3)
AS min_date,
TIMESTAMP '1970-01-01 00:00:00 UTC'
+ MAX(date_column) * INTERVAL '0.001' SECOND(3)
AS max_date,
place
FROM table_name
GROUP BY place;
Note: the (3) after SECOND is optional and will just explicitly specify the precision of the fractional seconds.
or:
SELECT TIMESTAMP '1970-01-01 00:00:00 UTC'
+ NUMTODSINTERVAL( MIN(date_column) / 1000, 'SECOND')
AS min_date,
TIMESTAMP '1970-01-01 00:00:00 UTC'
+ NUMTODSINTERVAL( MAX(date_column) / 1000, 'SECOND')
AS max_date,
place
FROM table_name
GROUP BY place;
Which, for the sample data:
CREATE TABLE table_name (ID, date_column, place) AS
SELECT 123, 1610295784376, 'OBJ_1' FROM DUAL UNION ALL
SELECT 444, 1748596758291, 'OBJ_1' FROM DUAL UNION ALL
SELECT 567, 1391749204754, 'OBJ_2' FROM DUAL UNION ALL -- Fixed leading digit
SELECT 888, 1747264526789, 'OBJ_3' FROM DUAL;
Both output:
MIN_DATE
MAX_DATE
PLACE
2021-01-10 16:23:04.376000000 UTC
2025-05-30 09:19:18.291000000 UTC
OBJ_1
2014-02-07 05:00:04.754000000 UTC
2014-02-07 05:00:04.754000000 UTC
OBJ_2
2025-05-14 23:15:26.789000000 UTC
2025-05-14 23:15:26.789000000 UTC
OBJ_3
db<>fiddle here

Time difference between manually entered time and datetimestamp field

I have a datetime field: PAYCOM_IN_TIME
I also have a manually entered field (ex: '07:00:00'): SCHEDULED_CLOCK_IN
SCHEDULED_CLOCK_IN is built using this in my query:
SELECT '07:00:00' SCHEDULED_CLOCK_IN FROM DUAL
I wish to get the time difference in MINUTES: PAYCOM_IN_TIME minus SCHEDULED_CLOCK_IN
All help is greatly appreciated!
I figured it out. I converted my hh:mm:ss text entry to a datetimestamp:
to_date(to_char(PAYCOM_DATE, 'MM-DD-YYYY') || S.CLOCK_IN, 'MM-DD-YYYY HH24:MI:SS')
Then I calculated Minutes:
(SCHEDULED_CLOCK_IN - P.CLOCKIN) * 24 * 60 DIFF_MINS
You can use:
SELECT paycom_in_time,
scheduled_clock_in,
( TRUNC( paycom_in_time ) + scheduled_clock_in - paycom_in_time ) DAY TO SECOND
AS difference_interval,
ROUND(
( TRUNC( paycom_in_time ) + scheduled_clock_in - paycom_in_time )
* 24 * 60
) AS difference_minutes
FROM table_name
CROSS JOIN (
SELECT INTERVAL '07:00' HOUR TO MINUTE AS scheduled_clock_in FROM DUAL
)
Which, for the sample data:
CREATE TABLE table_name ( paycom_in_time ) AS
SELECT DATE '2020-10-17' + INTERVAL '07:49' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT DATE '2020-10-13' + INTERVAL '06:51' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT DATE '2020-10-22' + INTERVAL '06:56' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT DATE '2020-10-23' + INTERVAL '06:47' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT DATE '2020-10-26' + INTERVAL '06:52' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT DATE '2020-10-30' + INTERVAL '06:59' HOUR TO MINUTE FROM DUAL;
Outputs:
PAYCOM_IN_TIME | SCHEDULED_CLOCK_IN | DIFFERENCE_INTERVAL | DIFFERENCE_MINUTES
:------------------ | :----------------- | :------------------ | -----------------:
2020-10-17 07:49:00 | +00 07:00:00 | -00 00:49:00.000000 | -49
2020-10-13 06:51:00 | +00 07:00:00 | +00 00:09:00.000000 | 9
2020-10-22 06:56:00 | +00 07:00:00 | +00 00:04:00.000000 | 4
2020-10-23 06:47:00 | +00 07:00:00 | +00 00:13:00.000000 | 13
2020-10-26 06:52:00 | +00 07:00:00 | +00 00:08:00.000000 | 8
2020-10-30 06:59:00 | +00 07:00:00 | +00 00:01:00.000000 | 1
db<>fiddle here
Use a query with
SELECT TIME_TO_SEC(TIMEDIFF(paycom, shedulded))/60;
Or
SELECT DATEDIFF(MINUTE, paycom, shedulded) AS [Time in Minutes]

cast two separate columns which has hour ( datatype number) and minutes ( datatype number) to time datatype and subtract 90 minutes in oracle

I have two separate columns for hours and minutes in my table and I have a report where i should be subtracting 90 minutes from total time put together or ( 1 hour from hour field) and 30 minutes from minutes field. The output can be in minutes or hours.
I tried "to_char ( hours_column -1,'00' ) || ':' || to_char ( minutes_column -30,'00' ) AS "MAX_TIME" " - this fails when I have time like 9:00 I get 8:-30 as the output when I need to get 7:30.
I came up with some sql code with DATEADD and cast functions which worked but it fails when I implement it in Oracle.
Select Substring(Cast(DATEADD(minute, -90, Cast(hourscolumn + ':' + minutes column as Time)) as varchar(20)),1,5) as max_time
Can someone help me to implement the above code in Oracle? I'm just trying to deduct 90 minutes by putting the hours and minutes columns together.
Something like this?
test CTE represents your data. How come you got that (bad) idea? Who/what prevents you from storing 32 hours and 87 minutes into those columns?
query itself contains
time: the way you create a valid date value. It'll fail if hours and/or minutes are invalid (such as previously mentioned 32:87)
subtracted: subtract 90 minutes from time; (24 * 60) represents 24 hours in a day, 60 minutes in an hour. It'll contain both date and time component
the final result is achieved by applying to_char with appropriate format mask (hh24:mi) to the subtracted value
SQL> alter session set nls_Date_format = 'dd.mm.yyyy hh24:mi';
Session altered.
SQL> with test (hours, minutes) as
2 (select '09', '00' from dual union all
3 select '23', '30' from dual union all
4 select '00', '20' from dual
5 )
6 select hours,
7 minutes,
8 to_date(hours||minutes, 'hh24mi') time,
9 --
10 to_date(hours||minutes, 'hh24mi') - 90 / (24 * 60) subtracted,
11 --
12 to_char(to_date(hours||minutes, 'hh24mi') - 90 / (24 * 60), 'hh24:mi') result
13 from test;
HO MI TIME SUBTRACTED RESUL
-- -- ---------------- ---------------- -----
09 00 01.07.2019 09:00 01.07.2019 07:30 07:30
23 30 01.07.2019 23:30 01.07.2019 22:00 22:00
00 20 01.07.2019 00:20 30.06.2019 22:50 22:50
SQL>
Use NUMTODSINTERVAL to convert the hours and minutes to INTERVAL data types and then you can subtract INTERVAL '90' MINUTE and EXTRACT the resulting hour and minute components.
Oracle Setup:
CREATE TABLE table_name ( hours_column, minutes_column ) AS
SELECT 0, 0 FROM DUAL UNION ALL
SELECT 1, 30 FROM DUAL UNION ALL
SELECT 2, 45 FROM DUAL UNION ALL
SELECT 3, 0 FROM DUAL UNION ALL
SELECT 27, 59 FROM DUAL
Query:
SELECT EXTRACT( HOUR FROM time ) + EXTRACT( DAY FROM time ) * 24 AS hours,
EXTRACT( MINUTE FROM time ) AS minutes,
time,
TO_CHAR( EXTRACT( HOUR FROM time ) + EXTRACT( DAY FROM time ) * 24, '00' )
|| ':' || TO_CHAR( ABS( EXTRACT( MINUTE FROM time ) ), 'FM00' ) AS as_string
FROM (
SELECT NUMTODSINTERVAL( hours_column, 'HOUR' )
+ NUMTODSINTERVAL( minutes_column, 'MINUTE' )
- INTERVAL '90' MINUTE AS time
FROM table_name
)
Output:
HOURS | MINUTES | TIME | AS_STRING
----: | ------: | :---------------------------- | :--------
-1 | -30 | -000000000 01:30:00.000000000 | -01:30
0 | 0 | +000000000 00:00:00.000000000 | 00:00
1 | 15 | +000000000 01:15:00.000000000 | 01:15
1 | 30 | +000000000 01:30:00.000000000 | 01:30
26 | 29 | +000000001 02:29:00.000000000 | 26:29
db<>fiddle here

how to convert HH:MM representation to minutes in oracle sql

how to convert varchar(hh:mm) to minutes in oracle sql.
For example:
HH:MM Minutes
08:00 480
08:45 525
07:57 477
This will work even if the duration is 24 hours or greater:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE durations ( duration ) AS
SELECT '00:30' FROM DUAL UNION ALL
SELECT '07:57' FROM DUAL UNION ALL
SELECT '08:00' FROM DUAL UNION ALL
SELECT '12:00' FROM DUAL UNION ALL
SELECT '20:01' FROM DUAL UNION ALL
SELECT '23:59' FROM DUAL UNION ALL
SELECT '24:00' FROM DUAL UNION ALL
SELECT '24:59' FROM DUAL;
Query 1:
SELECT duration,
( (
DATE '1970-01-01'
+ NUMTODSINTERVAL( SUBSTR( duration, 1, INSTR( duration, ':' ) - 1 ), 'HOUR' )
+ NUMTODSINTERVAL( SUBSTR( duration, INSTR( duration, ':' ) + 1 ), 'MINUTE' )
)
- DATE '1970-01-01'
) * 24 * 60 AS Minutes
FROM durations
Results:
| DURATION | MINUTES |
|----------|---------|
| 00:30 | 30 |
| 07:57 | 477 |
| 08:00 | 480 |
| 12:00 | 720 |
| 20:01 | 1201 |
| 23:59 | 1439 |
| 24:00 | 1440 |
| 24:59 | 1499 |
However, there is an INTERVAL DAY TO SECOND data type that would be better suited to your data:
CREATE TABLE your_table (
duration INTERVAL DAY TO SECOND
);
Then you can just do:
INSERT INTO your_table ( duration ) VALUES ( INTERVAL '08:00' HOUR TO MINUTE );
To get the number of minutes you can then simply do:
SELECT ( ( DATE '1970-01-01' + duration ) - DATE '1970-01-01' ) *24*60 AS minutes
FROM your_table
Try this
TO_NUMBER(SUBSTR('(08:00)',2,INSTR('(08:00)',':')-2))*60+TO_NUMBER(SUBSTR('(08:00)',INSTR('(08:00)',':')+1,2))
If you can convert your input to a real date first, the task becomes much easier. Here, I have shamelessly appended the time to a fake date to create a date such as 2017-01-01 00:30. To find out the number of minutes since midnight, you simply subtract the date for "midnight". It will return the difference in days, so you need to multiply by number of minutes per day to get what you want.
select time
,(to_date('2017-01-01 ' || time, 'yyyy-mm-dd hh24:mi') - date '2017-01-01') * 24 * 60 as minutes
from (select '00:30' as time from dual union all
select '08:00' as time from dual union all
select '08:30' as time from dual union all
select '12:00' as time from dual union all
select '23:59' as time from dual
);
Here is some sample input and output
time minutes
==== =======
00:30 30
08:00 480
08:30 510
12:00 720
23:59 1 439
If you require to Print 08:00 hours as 480 minutes,
Extract the Digit before : and multply with 60 and add the digit after :. So you can convert the HH:MM representation in to minutes.
SELECT REGEXP_SUBSTR(ATT.workdur,'[^:]+',1,1)*60 + REGEXP_SUBSTR(ATT.workdur,'[^:]+',1,2) MINUTES FROM DUAL;

Oracle : calculate duration between two dates in specific format

I would like to calculate the differnce between two dates (timestamp) but
in a specific format like DDd HH24:MI:SS.FF
As an example : 2d 10:25:30.350
There many examples on the net but most of them separate the days, hours, minutes.. in differents columns and not getting all of them in one column
Thanks
SQL Fiddle
Oracle 11g R2 Schema Setup:
Query 1:
WITH times ( start_time, end_time ) AS (
SELECT TIMESTAMP '2015-01-01 00:00:00', TIMESTAMP '2015-01-03 10:25:30.350' FROM DUAL
UNION ALL
SELECT TIMESTAMP '2015-01-01 00:00:00', TIMESTAMP '2015-01-01 09:00:00.000607' FROM DUAL
UNION ALL
SELECT TIMESTAMP '2015-03-01 00:00:00', TIMESTAMP '2016-03-01 00:00:00' FROM DUAL
UNION ALL
SELECT TIMESTAMP '2015-01-01 00:00:00', TIMESTAMP '2016-01-11 00:00:00' FROM DUAL
)
SELECT TO_CHAR( start_time, 'YYYY-MM-DD HH24:MI:SS.FF6' ) AS start_time,
TO_CHAR( end_time, 'YYYY-MM-DD HH24:MI:SS.FF6' ) AS end_time,
REGEXP_REPLACE( end_time - start_time, '^[+-]0*(\d+) 0?(\d+:\d{2}:\d{2}\.\d{3}\d*?)0*$', '\1d \2' ) AS time_difference
FROM times
Results:
| START_TIME | END_TIME | TIME_DIFFERENCE |
|----------------------------|----------------------------|-------------------|
| 2015-01-01 00:00:00.000000 | 2015-01-03 10:25:30.350000 | 2d 10:25:30.350 |
| 2015-01-01 00:00:00.000000 | 2015-01-01 09:00:00.000607 | 0d 9:00:00.000607 |
| 2015-03-01 00:00:00.000000 | 2016-03-01 00:00:00.000000 | 366d 0:00:00.000 |
| 2015-01-01 00:00:00.000000 | 2016-01-11 00:00:00.000000 | 375d 0:00:00.000 |
If you know that you will never have more than 365 days, you can use a valid date and only print the numbers. I'm thinking of something like this:
select (case when ts1 - ts2 < 1
then '000d ' || to_char(date '2000-01-01' + (t1 - t2), 'HH24:MI:SS')
else to_char(date '2000-01-01' + (t1 - t2) - 1, 'DDDd HH24:MI:SS')
end)
This does zero-pad the day component. It is easy enough to remove the leading zeros if that is desired.