I need a requirement to convert decimal value to time in sql query like if input is 12.5 it should return 12h 30m, if input is 8.70 it should return 8h 42m.
You could use Oracle's numtodsinterval function to achieve this.
select numtodsinterval(to_number('12.5'), 'hour') from dual;
Returns 0 12:30:0.0
select numtodsinterval(to_number('8.70'), 'hour') from dual;
Returns 0 8:42:0.0
Maintain such conversation into a intermediate table and keep mapping to transform
Create a SP to convert and done
If the format literally needs to be like "12h 30m" and "8h 42m", then the following could work:
WITH sample_data AS
(
SELECT NUMTODSINTERVAL(to_number('12.5'), 'HOUR') ds_interval FROM dual UNION ALL
SELECT NUMTODSINTERVAL(to_number('8.70'), 'HOUR') ds_interval FROM dual UNION ALL
SELECT NUMTODSINTERVAL(to_number('122.25'), 'HOUR') ds_interval FROM dual
)
SELECT ( (EXTRACT(DAY FROM sample_data.ds_interval) * 24) +
EXTRACT(HOUR FROM sample_data.ds_interval) ) || 'h ' ||
EXTRACT(MINUTE FROM sample_data.ds_interval) || 'm ' output
FROM sample_data;
OUTPUT
--------
12h 30m
8h 42m
122h 15m
The format could be expanded to convert hours to days when # of hours >= 24:
WITH sample_data AS
(
SELECT NUMTODSINTERVAL(to_number('122.25'), 'HOUR') ds_interval FROM dual
)
SELECT EXTRACT(DAY FROM sample_data.ds_interval) || 'd ' ||
EXTRACT(HOUR FROM sample_data.ds_interval) || 'h ' ||
EXTRACT(MINUTE FROM sample_data.ds_interval) || 'm '
FROM sample_data;
OUTPUT
---------
5d 2h 15m
There is a column 'DateTime' that displays the Date and Time in 'YYYY/MM/DD HH24:MI:SS' format.
I need to display only the rows that has time in a particular range(2AM - 6AM) regardless of the particular date.
I have a code that only displays the time range(2AM - 6AM) for the particular day. I need to display the rows that falls in the past 7 days with the time range 2AM-6AM.
SELECT *
FROM <table_name >
WHERE DateTime BETWEEN TO_DATE (
TO_CHAR (TRUNC (SYSDATE), 'DD-MM-YYYY')
|| ' '
|| '02:00:00',
'DD-MM-YYYY HH24:MI:SS')
AND TO_DATE (
TO_CHAR (TRUNC (SYSDATE), 'DD-MM-YYYY')
|| ' '
|| '06:00:00',
'DD-MM-YYYY HH24:MI:SS')
ORDER BY 1 DESC
SELECT *
FROM your_table
WHERE TO_CHAR( DateTime, 'HH24MMSS' ) BETWEEN '020000' AND '060000'
AND DateTime >= TRUNC( SYSDATE ) - INTERVAL '7' DAY
AND DateTime < TRUNC( SYSDATE ) + INTERVAL '1' DAY
or
SELECT *
FROM your_table
WHERE DateTime BETWEEN TRUNC( DateTime ) + INTERVAL '2' HOUR
AND TRUNC( DateTime ) + INTERVAL '6' HOUR
AND DateTime >= TRUNC( SYSDATE ) - INTERVAL '7' DAY
AND DateTime < TRUNC( SYSDATE ) + INTERVAL '1' DAY
You need two conditions for that: one for the hour being between 02 and 05, and one for the day being in the last seven days:
SELECT *
FROM <table_name>
WHERE to_char(DateTime, 'HH') BETWEEN '02' and '05' AND
DateTime BETWEEN SYSDATE - 7 AND SYSDATE
ORDER BY 1 DESC
In this case, I think the easiest way is string comparison:
WHERE SUBSTR(DateTime, 12, 2) BETWEEN '02' and '05'
Note: Between is inclusive so this should get everything up to 05:59:59.
SELECT *
FROM <table_name >
WHERE DateTime BETWEEN TO_DATE (
TO_CHAR (TRUNC (SYSDATE)-7, 'DD-MM-YYYY')
|| ' '
|| '02:00:00',
'DD-MM-YYYY HH24:MI:SS')
AND TO_DATE (
TO_CHAR (TRUNC (SYSDATE), 'DD-MM-YYYY')
|| ' '
|| '06:00:00',
'DD-MM-YYYY HH24:MI:SS')
select * from table_name where to_char(datetime,'HH24')
between '2' and '6' and to_char(datetime,'dd-mon-yy')
between to_char(sysdate,'dd-mon-yy') and to_char(sysdate-7,'dd-mon-yy');
I want to create a query that displays dates and counts. I want to display all dates within a range including dates with zero counts. I am looking for a way to do this WITHOUT using temp tables.
The output might look like:
Time Count
1/1/2017 01:00 AM 23
1/1/2017 02:00 AM 0
1/1/2017 03:00 AM 0
1/1/2017 04:00 AM 12
I was able to come up with an solutions that adds zero count rows. An example of the result set is below. You will see there are some duplicate DayOfWeekByHour values. I will need to figure out how to sum those up, but this is basically what I was looking for. See Example code link
DayOfWeekByHour, Count
100, 0
101, 0
102, 0
100, 23
201, 100
example of code
SELECT
TO_NUMBER(MOD(V,7)+1 || LPAD(MOD(V,24),2,'0')) as DayOfWeekByHour, 0
FROM (
SELECT 1 V FROM DUAL
) T
MODEL DIMENSION BY (ROWNUM R)
MEASURES (V)
RULES ITERATE (168) (
V[ITERATION_NUMBER] = CV(R) + 1
)
UNION
SELECT
TO_NUMBER(
TO_CHAR(
TO_DATE(
EXTRACT(MONTH FROM ve.CREATED_TIMESTAMP) || '/' ||
EXTRACT(DAY FROM ve.CREATED_TIMESTAMP) || '/' ||
EXTRACT(YEAR FROM ve.CREATED_TIMESTAMP) ,'MM/DD/YYYY'),'D'),'99') * 100 + TO_NUMBER(TO_CHAR(TO_DATE(
EXTRACT(MONTH FROM ve.CREATED_TIMESTAMP) || '/' ||
EXTRACT(DAY FROM ve.CREATED_TIMESTAMP) || '/' ||
EXTRACT(YEAR FROM ve.CREATED_TIMESTAMP) || ' ' ||
EXTRACT(HOUR FROM ve.CREATED_TIMESTAMP) || ':' ||
EXTRACT(MINUTE FROM ve.CREATED_TIMESTAMP)
,'MM/DD/YYYY HH24:MI'
)
,'HH24'
)
, '99') AS DayOfWeekByHour,
COUNT(*)
FROM
VIEWER.VIEWING_EVENT ve
WHERE
ve.CREATED_TIMESTAMP >= TO_TIMESTAMP('02-12-2016 00:00:00', 'dd-mm-yyyy hh24:mi:ss') AND
ve.CREATED_TIMESTAMP <= TO_TIMESTAMP('02-12-2017 00:00:00', 'dd-mm-yyyy hh24:mi:ss')
GROUP BY
TO_NUMBER(
TO_CHAR(
TO_DATE(
EXTRACT(MONTH FROM ve.CREATED_TIMESTAMP) || '/' ||
EXTRACT(DAY FROM ve.CREATED_TIMESTAMP) || '/' ||
EXTRACT(YEAR FROM ve.CREATED_TIMESTAMP) ,'MM/DD/YYYY'),'D'),'99') * 100 + TO_NUMBER(TO_CHAR(TO_DATE(
EXTRACT(MONTH FROM ve.CREATED_TIMESTAMP) || '/' ||
EXTRACT(DAY FROM ve.CREATED_TIMESTAMP) || '/' ||
EXTRACT(YEAR FROM ve.CREATED_TIMESTAMP) || ' ' ||
EXTRACT(HOUR FROM ve.CREATED_TIMESTAMP) || ':' ||
EXTRACT(MINUTE FROM ve.CREATED_TIMESTAMP)
,'MM/DD/YYYY HH24:MI'
)
,'HH24'
)
, '99')
ORDER BY
DayOfWeekByHour
;
The not like operator is not suitable for comparing values where the number of values is > 1 on a single work date. In the example below the records in the first 2 rows are a match (bold=bold, italic=italic) and should NOT appear in the output. The issue is caused by the ‘not like’ operator looping.
i have simplified the code as follows:
SELECT e.EMP_NAME AS APS,
TO_CHAR (ws.WRKS_WORK_DATE, 'dd.mm.yyyy') AS Work_Date,
TO_CHAR ( (wd.WRKD_START_TIME), 'hh24:mi') AS Leave_Start_Time,
TO_CHAR ( (wd.WRKD_end_TIME), 'hh24:mi') AS Leave_End_Time,
TO_CHAR (sb.SHFTBRK_DEF_START, 'hh24:mi') AS shift_brk_Start,
TO_CHAR (sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES + 1) * .000694,
'hh24:mi')
AS shift_brk_end
FROM work.WORK_SUMMARY ws,
work.employee e,
work.work_detail wd,
work.TIME_CODE tc,
work.shift s,
work.shift_break sb,
work.EMPLOYEE_SCHEDULE es
WHERE ws.emp_id = e.emp_id
AND wd.WRKD_MINUTES < s.SHFT_VAL1 ---sum workd minutes less than shift id actual shift minutes
AND ws.WRKS_WORK_DATE BETWEEN '09-Jul-2013' AND '09-Jul-2013'
AND wd.WRKS_ID = ws.WRKS_ID
AND tc.TCODE_name IN
('COMP', 'SL COMP PEN', 'ARB','LUC',
'CMF', 'MREP', 'WSSL', 'RL',
'CBK', 'JUR', 'LSL', 'LSLT',
'LWPNC', 'LWPS', 'LWPTC', 'LWPU',
'LWOP', 'ML', 'MLHP', 'NWPTC',
'PAT', 'PL', 'SD', 'MSP',
'SUS', 'SUSW', 'WIT', 'CMPA',
'ABC', 'ABN', 'BER', 'COM',
'COMWP', 'IS', 'EXL', 'LFI',
'MER', 'NCD', 'PCLC', 'PCLS',
'PSLC', 'PSLN', 'PSLW', 'PSWO',
'PSLP', 'PURL', 'STU', 'UA',
'GRTW')
AND wd.TCODE_ID = tc.TCODE_ID
AND ws.PAYGRP_ID IN ('10023')
AND ws.WRKS_AUTHORIZED = 'Y'
AND e.EMP_TERMINATION_DATE >= CURRENT_DATE
--and e.emp_name in('1100376801','1100590701')
AND ws.WRKS_WORK_DATE = es.WORK_DATE
AND ws.emp_id = es.emp_id
AND ws.shft_id = es.EMPSKD_ACT_SHIFT_ID
AND es.EMPSKD_ACT_SHIFT_ID = s.SHFT_ID
AND s.SHFT_ID = sb.SHFT_ID
AND ( ( TO_CHAR (sb.SHFTBRK_DEF_START, 'hh24:mi') <=
TO_CHAR ( (wd.WRKD_START_TIME), 'hh24:mi')
AND TO_CHAR (
sb.SHFTBRK_DEF_START
+ (sb.SHFTBRK_MINUTES + 1) * .000694,
'hh24:mi') >
TO_CHAR ( (wd.WRKD_START_TIME), 'hh24:mi'))
OR ( TO_CHAR (sb.SHFTBRK_DEF_START, 'hh24:mi') <
TO_CHAR ( (wd.WRKD_end_TIME), 'hh24:mi')
AND TO_CHAR (
sb.SHFTBRK_DEF_START
+ (sb.SHFTBRK_MINUTES + 1) * .000694,
'hh24:mi') > TO_CHAR ( (wd.WRKD_end_TIME), 'hh24:mi'))
OR ( TO_CHAR (sb.SHFTBRK_DEF_START, 'hh24:mi') >
TO_CHAR ( (wd.WRKD_START_TIME), 'hh24:mi')
AND TO_CHAR (
sb.SHFTBRK_DEF_START
+ (sb.SHFTBRK_MINUTES + 1) * .000694,
'hh24:mi') < TO_CHAR ( (wd.WRKD_end_TIME), 'hh24:mi'))
OR ( TO_CHAR (sb.SHFTBRK_DEF_START, 'hh24:mi') =
TO_CHAR ( (wd.WRKD_end_TIME), 'hh24:mi')
AND TO_CHAR (
sb.SHFTBRK_DEF_START
+ (sb.SHFTBRK_MINUTES + 1) * .000694,
'hh24:mi') = TO_CHAR ( (wd.WRKD_end_TIME), 'hh24:mi')))
GROUP BY e.EMP_NAME,
ws.WRKS_WORK_DATE,
wd.WRKD_end_TIME,
wd.WRKD_START_TIME,
sb.SHFTBRK_DEF_START,
TO_CHAR (sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES + 1) * .000694,
'hh24:mi');
Result:
APS WORK_DATE LEAVE_START_TIME LEAVE_END_TIME SHIFT_BRK_START SHIFT_BRK_END
-------------------------------------------------------------------------------------
40151401 09.07.2013 10:00 13:00 10:30 11:00
40200001 09.07.2013 09:00 12:51 10:00 10:30
40447701 09.07.2013 09:30 14:15 10:00 10:30
40492101 09.07.2013 15:00 20:10 16:00 16:30
61037301 09.07.2013 10:35 14:15 11:00 11:30
64173401 09.07.2013 09:30 14:15 10:00 10:30
The issue is that i am expecting to see a record for employee 1100376801.
The reason I can't see the record is because the times for the missing record fall over midnight, i.e 00:51. How can i format the 'datetime' fields differently so that times over midnight are picked up, i.e. where the SHIFT_BRK_START and SHIFT_BRK_END times span or fall within the LEAVE_START_TIME and LEAVE_END_TIME.
Expected result: in addition to the results returned above i should also see the following record:
APS WORK_DATE LEAVE_START_TIME LEAVE_END_TIME SHIFT_BRK_START SHIFT_BRK_END
-------------------------------------------------------------------------------------
11003701 09.07.2013 20:00 **0:51** 19:30 19:45
RESOLUTION:
and
(
(to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') < (wd.WRKD_START_TIME) and
to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES+1)*.000694, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') > (wd.WRKD_start_TIME))---1
OR(to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') =(wd.WRKD_START_TIME) and
to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES+1)*.000694, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') = (wd.WRKD_end_TIME))--4
OR(to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') =(wd.WRKD_START_TIME) and
to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES+1)*.000694, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') > (wd.WRKD_end_TIME))---5
OR(to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') =(wd.WRKD_START_TIME) and
to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES+1)*.000694, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') <(wd.WRKD_end_TIME))---5
OR (to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') > (wd.WRKD_START_TIME) and
to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES+1)*.000694, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') <= (wd.WRKD_end_TIME))---3
OR (to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') > (wd.WRKD_START_TIME) and
to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') < (wd.WRKD_end_TIME) and
to_date(to_char(wd.WRKD_START_TIME, 'dd.mm.yyyy') || '' || to_char(sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES+1)*.000694, 'hh24:mi'), 'dd.mm.yyyy hh24:mi') > (wd.WRKD_end_TIME))---2
)
Its still not clear about your requirement and data
Here are some points to check:
check the two below queries with 'ALTER SESSION NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI:SS';
(e.EMP_NAME || '_' || TO_CHAR(ws.WRKS_WORK_DATE,'dd.mm.yyyy') || '_' ||to_char(min(wd.WRKD_START_TIME), 'HH24:MI')|| '_' ||to_char(max(wd.WRKD_end_TIME), 'HH24:MI')) as test
(e.EMP_NAME || '_' || TO_CHAR(ws.WRKS_WORK_DATE,'dd.mm.yyyy') || '_' ||to_char(sb.SHFTBRK_DEF_START,'HH24:MI')|| '_' ||to_char(sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES+1)*.000694, 'HH24:MI')) as test
The condition for outermost query might not work as you expected,
not like operator will fail as your inner query for the column test is different.
where a_emp_break.test not like b_shift_break.test
and a_emp_break.APS=b_shift_break.APS
and a_emp_break.Work_Date = b_shift_break.Work_Date
you didn't mention the date you needed anywhere.
updating
check with the below outer query again:
TO_CHAR (sb.SHFTBRK_DEF_START + (sb.SHFTBRK_MINUTES + 1) * .000694, 'hh24:mi') AS shift_brk_end
AND ws.WRKS_WORK_DATE BETWEEN '09-Jul-2013' AND '09-Jul-2013' check the above includes the desired ids.
check again with the conditions with the to_date() funcition that accurating with < and > symbols.
Thanks.
We have a configuration table as shown below that stores the start time and the duration.
If the start time is 9:20 pm (3rd one ) add the duration then the time becomes 9:35.
I have to find out if the current time is in between any of the values.
I have to return the output based on the start_time and duration. i.e current time should be between start_time and the start_time + duration. (between 09:20 and and 09:35)
Can you please help me with the sql query or is it better if we go with sql function?
Start_time, duration(minutes) output
1108 5 2
1054 100 5
2120 15 8
I'm not a fan of storing dates and times in VARCHAR2 columns. START_TIME should really be a DATE or a TIMESTAMP column.
That said, you can do something like
with x as (
select '1108' start_time, 5 duration, 2 output from dual
union all
select '1054', 100, 5 from dual
union all
select '2120', 15, 8 from dual
)
select *
from (
select to_date(
to_char(sysdate,'YYYY-MM-DD') || ' ' ||
start_time,
'YYYY-MM-DD HH24MI' ) start_date,
to_date(
to_char(sysdate,'YYYY-MM-DD') || ' ' ||
start_time,
'YYYY-MM-DD HH24MI' ) + duration/24/60 end_date
from x)
where sysdate between start_date and end_date
The following selects all rows where sysdate is within the Start_Time and Start_Time + duration (EDITed as per comment from OP):
SELECT (TRUNC ( SYSDATE ) + TO_NUMBER ( SUBSTR ( Start_Time, 0, 2 ) ) / 24.0 + TO_NUMBER ( SUBSTR ( Start_Time, 3 ) ) / (24.0 * 60.0)) start_date, (TRUNC ( SYSDATE ) + TO_NUMBER ( SUBSTR ( Start_Time, 0, 2 ) ) / 24.0 + TO_NUMBER ( SUBSTR ( Start_Time, 3 ) ) / (24.0 * 60.0) + TO_NUMBER (duration)) end_date FROM configtable;