Oracle SQL populating a Time Dimension - sql

I'm writing a block of code to populate a time dimension in Oracle 11gR2 using SQL Developer
Table Structure
KEY Number(8,0)
HRS Varchar2
MINS Varchar2
SECS Varchar2
I'm new to PL/SQL - the way i would normally think of doing in pseudo-code would be but the for loops in PL/SQL don't seem to work this way:
key = 1
for (hrs=0; hr<=23; hr++)
{
for (min=0; min<=59; min++)
{
for (sec=0; sec<=59; sec++)
{
insert (KEY, tochar(hrs:mins:secs), tochar(hr), tochar(min), tochar(sec))
SK=+1
}
}
}
I've tried this from an answer i found:
insert into Dim_TIME
(Key,
TIME_IN24_NAME,
TIME_HOUR24,
TIME_MINUTE,
TIME_SECOND)
select
to_char(t, 'HH24:MI:SS'),
to_number(to_char(t, 'HH24'), '00'),
to_number(to_char(t, 'MI'), '00'),
to_number(to_char(t, 'SS'), '00')
from (
select trunc(sysdate) + (level - 1)/86400 as t
from dual
connect by level <= 86400
);
But not sure how i would increment the key (the column field is not auto-increment).
Any ideas how i could achieve this?
Thanks

You can create a SEQUENCE to increment the field KEY.
CREATE SEQUENCE dim_time_seq;
And use it in your code like this,
INSERT INTO dim_time
(KEY,
time_in24_name,
time_hour24,
time_minute,
time_second)
SELECT
dim_time_seq.nextval,
to_char(t, 'HH24:MI:SS'),
to_number(to_char(t, 'HH24'), '00'),
to_number(to_char(t, 'MI'), '00'),
to_number(to_char(t, 'SS'), '00')
FROM (
SELECT trunc(SYSDATE) + (LEVEL - 1)/86400 AS t
FROM dual
CONNECT BY LEVEL <= 86400
);

Related

Oracle converting working SQL with CTE to procedure

I have some SQL code, which works as designed. I'm trying to convert the code to a procedure to make it flexible so that different values maybe passed in.
I am running into an error while trying to create the procedure.
Errors: PROCEDURE CREATE_XXX
Line/Col: 28/1 PL/SQL: SQL Statement ignored
Line/Col: 37/3 PL/SQL: ORA-00928: missing SELECT keyword
The problem seems to be occurring in a CTE, which contains a SELECT so I'm a bit confused and can use some assistance.
Below is a test CASE that contains the working SQL along with the procedure I'm trying to create.
Thanks in advance for your help, patience and expertise and to all who answer.
ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';
create table schedule(
schedule_id NUMBER(4),
location_id number(4),
base_date DATE,
start_date DATE,
end_date DATE,
CONSTRAINT start_min check (start_date=trunc(start_date,'MI')),
CONSTRAINT end_min check (end_date=trunc(end_date,'MI')),
CONSTRAINT end_gt_start CHECK (end_date >= start_date),
CONSTRAINT same_day CHECK (TRUNC(end_date) = TRUNC(start_date))
);
/
CREATE TABLE locations AS
SELECT level AS location_id,
'Door ' || level AS location_name,
CASE round(dbms_random.value(1,3))
WHEN 1 THEN 'A'
WHEN 2 THEN 'T'
WHEN 3 THEN 'T'
END AS location_type
FROM dual
CONNECT BY level <= 15;
ALTER TABLE locations
ADD ( CONSTRAINT locations_pk
PRIMARY KEY (location_id));
-- works fine
WITH params AS
(
SELECT 1 AS schedule_id,
TO_DATE ( '2021-08-21 00:00:00'
, 'YYYY-MM-DD HH24:MI:SS'
) AS base_date
, INTERVAL '83760' SECOND AS offset
, INTERVAL '10' MINUTE AS incr
, INTERVAL '5' MINUTE AS duration
FROM dual
)
SELECT p.schedule_id
, l.location_id
, p.base_date
, p.base_date + offset
+ (incr * (ROWNUM - 1)) AS start_date
, p.base_date + offset
+ (incr * (ROWNUM - 1))
+ p.duration AS end_date
FROM locations l
CROSS JOIN params p
ORDER BY start_date
;
-- having problem
CREATE OR REPLACE PROCEDURE CREATE_XXX
(
i_schedule_id IN PLS_INTEGER,
i_base_date IN DATE,
i_offset IN PLS_INTEGER DEFAULT 0,
i_incr IN PLS_INTEGER DEFAULT 10,
i_duration IN PLS_INTEGER DEFAULT 5
)
AS
l_offset interval day to second;
l_incr interval day to second;
l_duration interval day to second;
BEGIN
l_offset :=
NUMTODSINTERVAL(i_offset, 'SECOND') ;
l_incr :=
NUMTODSINTERVAL(i_incr, 'MINUTE') ;
l_duration :=
NUMTODSINTERVAL(i_duration, 'MINUTE') ;
WITH params AS(
SELECT
i_schedule_id
,i_base_date
,l_offset
,l_incr
,l_duration
FROM DUAL
)
INSERT INTO schedule(
schedule_id
,location_id
,base_date
,start_date
,end_date
)
VALUES
(p.schedule_id
,l.location_id
,p.base_date
,start_date
,end_date
);
SELECT p.schedule_id
, l.location_id
, p.base_date
, p.base_date + p.offset
+ (p.incr * (ROWNUM - 1)) AS start_date
, p.base_date + p.offset
+ (p.incr * (ROWNUM - 1))
+ p.duration AS end_date
FROM locations l
CROSS JOIN params p
ORDER BY start_date;
END;
/
The issue is this statement.
WITH params AS(
SELECT
i_schedule_id
,i_base_date
,l_offset
,l_incr
,l_duration
FROM DUAL
)
INSERT INTO schedule(
schedule_id
,location_id
,base_date
,start_date
,end_date
)
VALUES
(p.schedule_id
,l.location_id
,p.base_date
,start_date
,end_date
);
I'm not sure what you're trying to accomplish. Syntactically, if you want to have a CTE as part of an insert, you'd want to do an insert ... select
INSERT INTO schedule(
schedule_id
,location_id
,base_date
,start_date
,end_date
)
WITH params AS(
SELECT
i_schedule_id
,i_base_date
,l_offset
,l_incr
,l_duration
FROM DUAL
)
SELECT
p.schedule_id
,l.location_id
,p.base_date
,start_date
,end_date
FROM params p;
From there, though, you've still got several syntax issues that it's not obvious how you'd want to solve all of them.
p.schedule_id isn't valid because there is no schedule_id column in the params CTE. My guess is that you want to alias i_schedule_id to schedule_id in the CTE.
l.location_id doesn't make sense because you're not selecting from a table that could plausibly be given an alias of l.
There is no base_date, start_date, or end_date column in your params CTE. And it's not obvious how you'd plausibly fix that.
Maybe you actually intended the subsequent select statement to actually be part of this insert statement despite the fact that you terminated the insert with a semicolon? If so, maybe you want
INSERT INTO schedule(
schedule_id
,location_id
,base_date
,start_date
,end_date
)
WITH params AS(
SELECT
i_schedule_id schedule_id
,i_base_date base_date
,l_offset offset
,l_incr incr
,l_duration duration
FROM DUAL
)
SELECT p.schedule_id
, l.location_id
, p.base_date
, p.base_date + p.offset
+ (p.incr * (ROWNUM - 1)) AS start_date
, p.base_date + p.offset
+ (p.incr * (ROWNUM - 1))
+ p.duration AS end_date
FROM locations l
CROSS JOIN params p
ORDER BY start_date;
That would produce code that compiles at least. There doesn't, however, appear to be any reason to bother with a CTE here at all. Just reference the local variables and input parameters directly. I've also eliminated the order by since it doesn't make sense in the context of an insert statement. I assume there is a reason that you need to take input parameters as integers and convert them to local variables with the same name and a different data type rather than just passing in interval parameters to the procedure. If you can do that, you can further simplify things by eliminating the local variables.
CREATE OR REPLACE PROCEDURE CREATE_XXX
(
i_schedule_id IN PLS_INTEGER,
i_base_date IN DATE,
i_offset IN PLS_INTEGER DEFAULT 0,
i_incr IN PLS_INTEGER DEFAULT 10,
i_duration IN PLS_INTEGER DEFAULT 5
)
AS
l_offset interval day to second;
l_incr interval day to second;
l_duration interval day to second;
BEGIN
l_offset :=
NUMTODSINTERVAL(i_offset, 'SECOND') ;
l_incr :=
NUMTODSINTERVAL(i_incr, 'MINUTE') ;
l_duration :=
NUMTODSINTERVAL(i_duration, 'MINUTE') ;
INSERT INTO schedule(
schedule_id
,location_id
,base_date
,start_date
,end_date
)
SELECT i_schedule_id
, l.location_id
, i_base_date
, i_base_date + l_offset
+ (l_incr * (ROWNUM - 1)) AS start_date
, i_base_date + l_offset
+ (l_incr * (ROWNUM - 1))
+ l_duration AS end_date
FROM locations l;
END;
/

SQL INSERT INTO simultaneously in 2 tables in apex oracle

I have a script:
I write the data in test2!
INSERT INTO test2 (val)
SELECT SUBSTR (:P1_FIRST, 1, 1)
|| TO_CHAR (
( TO_NUMBER (REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ LEVEL
- 1))
AS val
FROM dual
CONNECT BY LEVEL <=
TO_NUMBER (
REGEXP_SUBSTR (:P1_LAST, '\d+$'))
- TO_NUMBER (
REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ 1;
I want to write it in another table myself.I want to write it down all in one request
INSERT INTO test3 (val,data_area,data_add )
SELECT SUBSTR (:P1_FIRST, 1, 1)
|| TO_CHAR (
( TO_NUMBER (REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ LEVEL
- 1))
AS val,
(select data_area from SEC_USERS_LIST where login = LOWER(:APP_USER)) as data_area,
(select to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') "Right Now" from dual ) as data_add
FROM dual
CONNECT BY LEVEL <=
TO_NUMBER (
REGEXP_SUBSTR (:P1_LAST, '\d+$'))
- TO_NUMBER (
REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ 1;
You could try and use Oracle INSERT ALL syntax :
In a multitable insert, you insert computed rows derived from the rows returned from the evaluation of a subquery into one or more tables.
ALL into_clause
Specify ALL followed by multiple insert_into_clauses to perform an unconditional multitable insert. Oracle Database executes each insert_into_clause once for each row returned by the subquery.
Consider:
INSERT ALL
INTO test3 (val,data_area,data_add) VALUES (x_val, x_data_area, x_data_add)
INTO test2 (val) VALUES (x_val)
SELECT SUBSTR (:P1_FIRST, 1, 1)
|| TO_CHAR (
( TO_NUMBER (REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ LEVEL
- 1))
AS x_val,
(select data_area from SEC_USERS_LIST where login = LOWER(:APP_USER)) as x_data_area,
(select to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') "Right Now" from dual ) as x_data_add
FROM dual
CONNECT BY LEVEL <=
TO_NUMBER (REGEXP_SUBSTR (:P1_LAST, '\d+$'))
- TO_NUMBER (REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ 1
;
NB: as far as concerns, the inline subquery that returns the current date is not needed and could be simplified as just:
to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') as x_data_add
Instead of:
(select to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') "Right Now" from dual ) as x_data_add
Even more, as commented by Thomas Tschernich: if x_data_add is of datatype DATE, no casting should be necessary and you could simply use a default on the table column and omit it from the INSERT completely

Oracle SQL group row count by time intervals of 10 minutes

I have a table in oracle which contains data such as the following
created_date details
01-Jan-16 04:45 abcd
01-Jan-16 04:47 efgh
01-Jan-16 04:53 ijkl
01-Jan-16 04:54 mnop
01-Jan-16 04:58 qrst
....etc
I want to be able to count the number of rows in the table for every 10 minutes
e.g.
Time count
04:40 2
04:50 3
Created Date = Timestamp,
details = varchar
How would i do this?
Thanks
You can use TO_CHAR and SUBSTR to build the time string:
select
substr(to_char(created_date, 'hh24:mi'), 1, 4) || '0' as created,
count(*)
from mytable
group by substr(to_char(created_date, 'hh24:mi'), 1, 4) || '0'
order by substr(to_char(created_date, 'hh24:mi'), 1, 4) || '0';
Or with a subquery (a derived table), so as to have to write the date expression only once:
select created, count(*)
from
(
select substr(to_char(created_date, 'hh24:mi'), 1, 4) || '0' as created
from mytable
)
group by created
order by created;
One method is to extract the hour and minute and do arithmetic:
select extract(hour from created_date) as hh,
floor(extract(minute from created_date) / 6) as min,
count(*)
from t
group by extract(hour from created_date),
floor(extract(minute from created_date) / 6)
An answer would be:
select trunc(sysdate, 'hh')+ trunc(to_char(sysdate,'mi')/10)*10/1440 from dual;
You can replace sysdate with your actual date/timestamp column and dual with your table
To understand the components, run:
select trunc(sysdate, 'hh') the_hour,
to_char(sysdate,'mi') the_minutes,
trunc(to_char(sysdate,'mi')/10)*10 minutes_truncated,
trunc(to_char(sysdate,'mi')/10)*10/1440 part_of_the_day, --as 1 represents a day in oracle datetime system
trunc(sysdate, 'hh')+ trunc(to_char(sysdate,'mi')/10)*10/1440 result
from dual;
Here's a solution if you want to make the group by on an actual timestamp value:
create table test_10_minutes_group_by (created_date timestamp, details varchar2(4));
insert into test_10_minutes_group_by values (systimestamp, 'aaa'); -- current time
insert into test_10_minutes_group_by values (systimestamp - 1/24/60, 'bbb'); -- 1 minute ago
insert into test_10_minutes_group_by values (systimestamp - 1/24/60 * 10, 'ccc'); -- 10 minutes ago
insert into test_10_minutes_group_by values (systimestamp - 1/24/60 * 20, 'ccc2'); -- 20 minutes ago
insert into test_10_minutes_group_by values (systimestamp - 1/24/60 * 25, 'abc'); -- 25 minutes ago
insert into test_10_minutes_group_by values (systimestamp - 1/24/60 * 30, 'xyz'); -- 30 minutes ago
insert into test_10_minutes_group_by values (systimestamp - 1/24/60 * 35, 'xyz2'); -- 35 minutes ago
select
actual_time,
to_char(actual_time, 'hh24:mi:ss') pretty_date,
count(1)
from (
select
trunc(created_date, 'mi') /*remove seconds*/ - 1/24/60 * mod(extract (minute from created_date), 10) /*substract units digit from minutes*/ actual_time,
details
from
test_10_minutes_group_by
)
group by actual_time;

SQL filter query output based on difference of two timestamp field [duplicate]

I have a table as follows:
Filename - varchar
Creation Date - Date format dd/mm/yyyy hh24:mi:ss
Oldest cdr date - Date format dd/mm/yyyy hh24:mi:ss
How can I calcuate the difference in hours minutes and seconds (and possibly days) between the two dates in Oracle SQL?
Thanks
You can substract dates in Oracle. This will give you the difference in days. Multiply by 24 to get hours, and so on.
SQL> select oldest - creation from my_table;
If your date is stored as character data, you have to convert it to a date type first.
SQL> select 24 * (to_date('2009-07-07 22:00', 'YYYY-MM-DD hh24:mi')
- to_date('2009-07-07 19:30', 'YYYY-MM-DD hh24:mi')) diff_hours
from dual;
DIFF_HOURS
----------
2.5
Note:
This answer applies to dates represented by the Oracle data type DATE.
Oracle also has a data type TIMESTAMP, which can also represent a date (with time). If you subtract TIMESTAMP values, you get an INTERVAL; to extract numeric values, use the EXTRACT function.
To get result in seconds:
select (END_DT - START_DT)*60*60*24 from MY_TABLE;
Check [https://community.oracle.com/thread/2145099?tstart=0][1]
select
extract( day from diff ) Days,
extract( hour from diff ) Hours,
extract( minute from diff ) Minutes
from (
select (CAST(creationdate as timestamp) - CAST(oldcreationdate as timestamp)) diff
from [TableName]
);
This will give you three columns as Days, Hours and Minutes.
declare
strTime1 varchar2(50) := '02/08/2013 01:09:42 PM';
strTime2 varchar2(50) := '02/08/2013 11:09:00 PM';
v_date1 date := to_date(strTime1,'DD/MM/YYYY HH:MI:SS PM');
v_date2 date := to_date(strTime2,'DD/MM/YYYY HH:MI:SS PM');
difrence_In_Hours number;
difrence_In_minutes number;
difrence_In_seconds number;
begin
difrence_In_Hours := (v_date2 - v_date1) * 24;
difrence_In_minutes := difrence_In_Hours * 60;
difrence_In_seconds := difrence_In_minutes * 60;
dbms_output.put_line(strTime1);
dbms_output.put_line(strTime2);
dbms_output.put_line('*******');
dbms_output.put_line('difrence_In_Hours : ' || difrence_In_Hours);
dbms_output.put_line('difrence_In_minutes: ' || difrence_In_minutes);
dbms_output.put_line('difrence_In_seconds: ' || difrence_In_seconds);
end ;
Hope this helps.
You may also try this:
select to_char(to_date('1970-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')+(end_date - start_date),'hh24:mi:ss')
as run_time from some_table;
It displays time in more human readable form, like: 00:01:34.
If you need also days you may simply add DD to last formatting string.
Calculate age from HIREDATE to system date of your computer
SELECT HIREDATE||' '||SYSDATE||' ' ||
TRUNC(MONTHS_BETWEEN(SYSDATE,HIREDATE)/12) ||' YEARS '||
TRUNC((MONTHS_BETWEEN(SYSDATE,HIREDATE))-(TRUNC(MONTHS_BETWEEN(SYSDATE,HIREDATE)/12)*12))||
'MONTHS' AS "AGE " FROM EMP;
You could use to_timestamp function to convert the dates to timestamps and perform a substract operation.
Something like:
SELECT
TO_TIMESTAMP ('13.10.1990 00:00:00','DD.MM.YYYY HH24:MI:SS') -
TO_TIMESTAMP ('01.01.1990:00:10:00','DD.MM.YYYY:HH24:MI:SS')
FROM DUAL
In oracle 11g
SELECT end_date - start_date AS day_diff FROM tablexxx
suppose the starT_date end_date is define in the tablexxx
select days||' '|| time from (
SELECT to_number( to_char(to_date('1','J') +
(CLOSED_DATE - CREATED_DATE), 'J') - 1) days,
to_char(to_date('00:00:00','HH24:MI:SS') +
(CLOSED_DATE - CREATED_DATE), 'HH24:MI:SS') time
FROM request where REQUEST_ID=158761088 );
If you want something that looks a bit simpler, try this for finding events in a table which occurred in the past 1 minute:
With this entry you can fiddle with the decimal values till you get the minute value that you want. The value .0007 happens to be 1 minute as far as the sysdate significant digits are concerned. You can use multiples of that to get any other value that you want:
select (sysdate - (sysdate - .0007)) * 1440 from dual;
Result is 1 (minute)
Then it is a simple matter to check for
select * from my_table where (sysdate - transdate) < .00071;
If you select two dates from 'your_table' and want too see the result as a single column output (eg. 'days - hh:mm:ss') you could use something like this.
First you could calculate the interval between these two dates and after that export all the data you need from that interval:
select extract (day from numtodsinterval (second_date
- add_months (created_date,
floor (months_between (second_date,created_date))),
'day'))
|| ' days - '
|| extract (hour from numtodsinterval (second_date
- add_months (created_date,
floor (months_between (second_date,created_date))),
'day'))
|| ':'
|| extract (minute from numtodsinterval (second_date
- add_months (created_date,
floor (months_between (second_date, created_date))),
'day'))
|| ':'
|| extract (second from numtodsinterval (second_date
- add_months (created_date,
floor (months_between (second_date, created_date))),
'day'))
from your_table
And that should give you result like this:
0 days - 1:14:55
select (floor(((DATE2-DATE1)*24*60*60)/3600)|| ' : ' ||floor((((DATE2-DATE1)*24*60*60) -floor(((DATE2-DATE1)*24*60*60)/3600)*3600)/60)|| ' ' ) as time_difference from TABLE1
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*60*60*24 sum_seconds,
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*60*24 sum_minutes,
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*24 sum_hours,
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi')) sum_days
select to_char(actual_start_date,'DD-MON-YYYY hh24:mi:ss') start_time,
to_char(actual_completion_date,'DD-MON-YYYY hh24:mi:ss') end_time,
floor((actual_completion_date-actual_start_date)*24*60)||'.'||round(mod((actual_completion_date-actual_start_date)*24*60*60,60)) diff_time
from fnd_concurrent_requests
order by request_id desc;
If You want get date defer from using table and column.
SELECT TO_DATE( TO_CHAR(COLUMN_NAME_1, 'YYYY-MM-DD'), 'YYYY-MM-DD') -
TO_DATE(TO_CHAR(COLUMN_NAME_2, 'YYYY-MM-DD') , 'YYYY-MM-DD') AS DATEDIFF
FROM TABLE_NAME;
This will count time between to dates:
SELECT
(TO_CHAR( TRUNC (ROUND(((sysdate+1) - sysdate)*24,2))*60,'999999')
+
TO_CHAR(((((sysdate+1)-sysdate)*24)- TRUNC(ROUND(((sysdate+1) - sysdate)*24,2)))/100*60 *100, '09'))/60
FROM dual
Here's another option:
with tbl_demo AS
(SELECT TO_DATE('11/26/2013 13:18:50', 'MM/DD/YYYY HH24:MI:SS') dt1
, TO_DATE('11/28/2013 21:59:12', 'MM/DD/YYYY HH24:MI:SS') dt2
FROM dual)
SELECT dt1
, dt2
, round(dt2 - dt1,2) diff_days
, round(dt2 - dt1,2)*24 diff_hrs
, numtodsinterval((dt2 - dt1),'day') diff_dd_hh_mm_ss
from tbl_demo;
Single query that will return time difference of two timestamp columns:
select INS_TS, MAIL_SENT_TS, extract( hour from (INS_TS - MAIL_SENT_TS) ) timeDiff
from MAIL_NOTIFICATIONS;
select round( (tbl.Todate - tbl.fromDate) * 24 * 60 * 60 )
from table tbl
for oracle sql I justbn did this and works perfect :
SELECT trunc(date_col_1) - trunc(date_col_2)
FROM TABLE;
$sql="select bsp_bp,user_name,status,
to_char(ins_date,'dd/mm/yyyy hh12:mi:ss AM'),
to_char(pickup_date,'dd/mm/yyyy hh12:mi:ss AM'),
trunc((pickup_date-ins_date)*24*60*60,2),message,status_message
from valid_bsp_req where id >= '$id'";

Subtracting the difference between two time intervals in oracle sql [duplicate]

I have a table as follows:
Filename - varchar
Creation Date - Date format dd/mm/yyyy hh24:mi:ss
Oldest cdr date - Date format dd/mm/yyyy hh24:mi:ss
How can I calcuate the difference in hours minutes and seconds (and possibly days) between the two dates in Oracle SQL?
Thanks
You can substract dates in Oracle. This will give you the difference in days. Multiply by 24 to get hours, and so on.
SQL> select oldest - creation from my_table;
If your date is stored as character data, you have to convert it to a date type first.
SQL> select 24 * (to_date('2009-07-07 22:00', 'YYYY-MM-DD hh24:mi')
- to_date('2009-07-07 19:30', 'YYYY-MM-DD hh24:mi')) diff_hours
from dual;
DIFF_HOURS
----------
2.5
Note:
This answer applies to dates represented by the Oracle data type DATE.
Oracle also has a data type TIMESTAMP, which can also represent a date (with time). If you subtract TIMESTAMP values, you get an INTERVAL; to extract numeric values, use the EXTRACT function.
To get result in seconds:
select (END_DT - START_DT)*60*60*24 from MY_TABLE;
Check [https://community.oracle.com/thread/2145099?tstart=0][1]
select
extract( day from diff ) Days,
extract( hour from diff ) Hours,
extract( minute from diff ) Minutes
from (
select (CAST(creationdate as timestamp) - CAST(oldcreationdate as timestamp)) diff
from [TableName]
);
This will give you three columns as Days, Hours and Minutes.
declare
strTime1 varchar2(50) := '02/08/2013 01:09:42 PM';
strTime2 varchar2(50) := '02/08/2013 11:09:00 PM';
v_date1 date := to_date(strTime1,'DD/MM/YYYY HH:MI:SS PM');
v_date2 date := to_date(strTime2,'DD/MM/YYYY HH:MI:SS PM');
difrence_In_Hours number;
difrence_In_minutes number;
difrence_In_seconds number;
begin
difrence_In_Hours := (v_date2 - v_date1) * 24;
difrence_In_minutes := difrence_In_Hours * 60;
difrence_In_seconds := difrence_In_minutes * 60;
dbms_output.put_line(strTime1);
dbms_output.put_line(strTime2);
dbms_output.put_line('*******');
dbms_output.put_line('difrence_In_Hours : ' || difrence_In_Hours);
dbms_output.put_line('difrence_In_minutes: ' || difrence_In_minutes);
dbms_output.put_line('difrence_In_seconds: ' || difrence_In_seconds);
end ;
Hope this helps.
You may also try this:
select to_char(to_date('1970-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')+(end_date - start_date),'hh24:mi:ss')
as run_time from some_table;
It displays time in more human readable form, like: 00:01:34.
If you need also days you may simply add DD to last formatting string.
Calculate age from HIREDATE to system date of your computer
SELECT HIREDATE||' '||SYSDATE||' ' ||
TRUNC(MONTHS_BETWEEN(SYSDATE,HIREDATE)/12) ||' YEARS '||
TRUNC((MONTHS_BETWEEN(SYSDATE,HIREDATE))-(TRUNC(MONTHS_BETWEEN(SYSDATE,HIREDATE)/12)*12))||
'MONTHS' AS "AGE " FROM EMP;
You could use to_timestamp function to convert the dates to timestamps and perform a substract operation.
Something like:
SELECT
TO_TIMESTAMP ('13.10.1990 00:00:00','DD.MM.YYYY HH24:MI:SS') -
TO_TIMESTAMP ('01.01.1990:00:10:00','DD.MM.YYYY:HH24:MI:SS')
FROM DUAL
In oracle 11g
SELECT end_date - start_date AS day_diff FROM tablexxx
suppose the starT_date end_date is define in the tablexxx
select days||' '|| time from (
SELECT to_number( to_char(to_date('1','J') +
(CLOSED_DATE - CREATED_DATE), 'J') - 1) days,
to_char(to_date('00:00:00','HH24:MI:SS') +
(CLOSED_DATE - CREATED_DATE), 'HH24:MI:SS') time
FROM request where REQUEST_ID=158761088 );
If you want something that looks a bit simpler, try this for finding events in a table which occurred in the past 1 minute:
With this entry you can fiddle with the decimal values till you get the minute value that you want. The value .0007 happens to be 1 minute as far as the sysdate significant digits are concerned. You can use multiples of that to get any other value that you want:
select (sysdate - (sysdate - .0007)) * 1440 from dual;
Result is 1 (minute)
Then it is a simple matter to check for
select * from my_table where (sysdate - transdate) < .00071;
If you select two dates from 'your_table' and want too see the result as a single column output (eg. 'days - hh:mm:ss') you could use something like this.
First you could calculate the interval between these two dates and after that export all the data you need from that interval:
select extract (day from numtodsinterval (second_date
- add_months (created_date,
floor (months_between (second_date,created_date))),
'day'))
|| ' days - '
|| extract (hour from numtodsinterval (second_date
- add_months (created_date,
floor (months_between (second_date,created_date))),
'day'))
|| ':'
|| extract (minute from numtodsinterval (second_date
- add_months (created_date,
floor (months_between (second_date, created_date))),
'day'))
|| ':'
|| extract (second from numtodsinterval (second_date
- add_months (created_date,
floor (months_between (second_date, created_date))),
'day'))
from your_table
And that should give you result like this:
0 days - 1:14:55
select (floor(((DATE2-DATE1)*24*60*60)/3600)|| ' : ' ||floor((((DATE2-DATE1)*24*60*60) -floor(((DATE2-DATE1)*24*60*60)/3600)*3600)/60)|| ' ' ) as time_difference from TABLE1
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*60*60*24 sum_seconds,
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*60*24 sum_minutes,
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*24 sum_hours,
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi')) sum_days
select to_char(actual_start_date,'DD-MON-YYYY hh24:mi:ss') start_time,
to_char(actual_completion_date,'DD-MON-YYYY hh24:mi:ss') end_time,
floor((actual_completion_date-actual_start_date)*24*60)||'.'||round(mod((actual_completion_date-actual_start_date)*24*60*60,60)) diff_time
from fnd_concurrent_requests
order by request_id desc;
If You want get date defer from using table and column.
SELECT TO_DATE( TO_CHAR(COLUMN_NAME_1, 'YYYY-MM-DD'), 'YYYY-MM-DD') -
TO_DATE(TO_CHAR(COLUMN_NAME_2, 'YYYY-MM-DD') , 'YYYY-MM-DD') AS DATEDIFF
FROM TABLE_NAME;
This will count time between to dates:
SELECT
(TO_CHAR( TRUNC (ROUND(((sysdate+1) - sysdate)*24,2))*60,'999999')
+
TO_CHAR(((((sysdate+1)-sysdate)*24)- TRUNC(ROUND(((sysdate+1) - sysdate)*24,2)))/100*60 *100, '09'))/60
FROM dual
Here's another option:
with tbl_demo AS
(SELECT TO_DATE('11/26/2013 13:18:50', 'MM/DD/YYYY HH24:MI:SS') dt1
, TO_DATE('11/28/2013 21:59:12', 'MM/DD/YYYY HH24:MI:SS') dt2
FROM dual)
SELECT dt1
, dt2
, round(dt2 - dt1,2) diff_days
, round(dt2 - dt1,2)*24 diff_hrs
, numtodsinterval((dt2 - dt1),'day') diff_dd_hh_mm_ss
from tbl_demo;
Single query that will return time difference of two timestamp columns:
select INS_TS, MAIL_SENT_TS, extract( hour from (INS_TS - MAIL_SENT_TS) ) timeDiff
from MAIL_NOTIFICATIONS;
select round( (tbl.Todate - tbl.fromDate) * 24 * 60 * 60 )
from table tbl
for oracle sql I justbn did this and works perfect :
SELECT trunc(date_col_1) - trunc(date_col_2)
FROM TABLE;
$sql="select bsp_bp,user_name,status,
to_char(ins_date,'dd/mm/yyyy hh12:mi:ss AM'),
to_char(pickup_date,'dd/mm/yyyy hh12:mi:ss AM'),
trunc((pickup_date-ins_date)*24*60*60,2),message,status_message
from valid_bsp_req where id >= '$id'";