no rule, use for any inbuild function, i have a number of forms and different edition dates so i showing sample data. first, i am matched check the FORM_NO column the last four digits with the Edition_Date column. if matched then the FORM_NO column the last four digits are skipped and concatenations with the Edition_Date column else as it is show.For example when i am trying below query executed.
with FOrm as (select 'GL-GEN-CHANGE-ENDT-MISC-OLD' Form_No, '05-05' Edition_Date from dual
union all
select 'CM59930202' Form_No, '02-02' Edition_Date from dual
union all
select '99109 06 08' Form_No, '06-08' Edition_Date from dual
union all
select 'IM 7978 08 12' Form_No, '08-12' Edition_Date from dual
union all
select 'IL01220907' Form_No, '09-07' Edition_Date from dual
union all
select 'PRG 2023 05 14' Form_No, '05-14' Edition_Date from dual)
select Form_No,case when SUBSTR(REGEXP_REPLACE( Form_No, '[^[:alnum:]]', NULL ),-4)=REGEXP_REPLACE( Edition_Date, '[^[:alnum:]]', NULL )
then substr(Form_No, 0, length(Form_No)-4)||' '||Edition_Date end as REC1,
case when SUBSTR(REGEXP_REPLACE( Form_No, '[^[:alnum:]]', NULL ),-4)=REGEXP_REPLACE( Edition_Date, '[^[:alnum:]]', NULL )
then substr(Form_No, 0, length(REGEXP_REPLACE( Form_No, '[^[:alnum:]]', NULL ))-4)||' '||Edition_Date
when regexp_count(Form_No,'[^ [:alnum:]]')>2 then Form_No||' '||Edition_Date
when regexp_count(Form_No,'[^-[:alnum:]]')>2 then SUBSTR(REGEXP_REPLACE( Form_No, '[^[:alnum:]]', NULL ),-5)||' '||Edition_Date
end REC2 from FOrm
I showed the following output after executing the query
FORM_NO Edition_Date REC1 REC2
---------------------------- ------------- ---------------- --------------------
GL-GEN-CHANGE-ENDT-MISC-OLD 05-05 NULL GL-GEN-CHANGE-ENDT-MISC-OLD 05-05
CM59930202 02-02 CM5993 02-02 CM5993 02-02
99109 06 08 06-08 99109 0 06-08 99109 06-08
IM 7978 08 12 08-12 IM 7978 0 08-12 IM 797 08-12
IL01220907 09-07 IL0122 09-07 IL0122 09-07
PRG 2023 05 14 05-14 PRG 2023 0 05-14 PRG 202 05-14
The expectation result
FORM_NO REC1 REC2
----------------------------------------------------------- ------------------------------------
GL-GEN-CHANGE-ENDT-MISC-OLD GL-GEN-CHANGE-ENDT-MISC-OLD GL-GEN-CHANGE-ENDT-MISC-OLD
CM59930202 CM5993 02-02 CM5993 02-02
99109 06 08 99109 06-08 99109 06-08
IM 7978 08 12 IM7978 08-12 IM 7978 08-12
IL01220907 IL0122 09-07 IL0122 09-07
PRG 2023 05 14 PRG2023 05-14 PRG 2023 05-14
Here is a regex that gives you your wanted output, you didn't mention any rule only wanted output so here it is:
with FOrm as
(
select 'GL-GEN-CHANGE-ENDT-MISC-OLD' Form_No, '05-05' Edition_Date from dual
union all
select 'CM59930202' Form_No, '02-02' Edition_Date from dual
union all
select '99109 06 08' Form_No, '06-08' Edition_Date from dual
union all
select 'IM 7978 08 12' Form_No, '08-12' Edition_Date from dual
union all
select 'IL01220907' Form_No, '09-07' Edition_Date from dual
union all
select 'PRG 2023 05 14' Form_No, '05-14' Edition_Date from dual)
select Form_No,
case
when not regexp_like(Form_No,'[0-9]{1}') then Form_No
when regexp_like(trim(Form_No),'^[A-Za-z]{1,}[[:space:]]{1,}') then
regexp_substr(Form_No,'^[A-Za-z]{1,}')||regexp_substr(Form_No,'[0-9]{1,}')||' '||
Edition_Date
when regexp_like(Form_No,'^[0-9]{1,}') then Form_No
when regexp_like(Form_No,'^[A-Za-z]{1,}[0-9]{1,}') then
regexp_substr(Form_No,'^[A-Za-z]{1,}')||regexp_substr(Form_No,'[0-9]{4}')||' '||
Edition_Date
end as rec1,
case
when not regexp_like(Form_No,'[0-9]{1}') then Form_No
when regexp_like(trim(Form_No),'^[A-Za-z]{1,}[[:space:]]{1,}') then
regexp_substr(Form_No,'^[A-Za-z]{1,}')||' '||regexp_substr(Form_No,'[0-9]{1,}')||' '||
Edition_Date
when regexp_like(Form_No,'^[0-9]{1,}') then Form_No
when regexp_like(Form_No,'^[A-Za-z]{1,}[0-9]{1,}') then
regexp_substr(Form_No,'^[A-Za-z]{1,}')||regexp_substr(Form_No,'[0-9]{4}')||' '||
Edition_Date
end as rec2
from FOrm
RESULT:
FORM_NO REC1 REC2
------------------------------------------------------------------------------------
GL-GEN-CHANGE-ENDT-MISC-OLD GL-GEN-CHANGE-ENDT-MISC-OLD GL-GEN-CHANGE-ENDT-MISC-OLD
CM59930202 CM5993 02-02 CM5993 02-02
99109 06 08 99109 06 08 99109 06 08
IM 7978 08 12 IM7978 08-12 IM 7978 08-12
IL01220907 IL0122 09-07 IL0122 09-07
PRG 2023 05 14 PRG2023 05-14 PRG 2023 05-14
Related
I have a table with normal DATE field in it:
5/9/2022 2:32:02 AM
5/9/2022 12:33:02 PM
5/9/2022 10:34:02 AM
5/9/2022 10:20:02 AM
5/9/2022 6:54:02 AM
5/9/2022 4:28:02 AM
5/9/2022 5:08:02 AM
I need a query that I can run that will give me the record that is the closest to the top of the hour I am asking for. So like, which is closest to 5:00am, or 7:00am, or 12:00pm.
Thanks!
A query like the one below can be used to show each record that is closest to the "top of the hour". In your sample data, none of the records overlap to the nearest "top of the hour", so all the records will be shown. If you add additional dates that are closer together to the top of the hour, then only the the dates closest to the "top of the hour" will be shown.
Query
WITH
sample_dates (dt)
AS
(SELECT TO_DATE ('5/9/2022 2:32:02 AM', 'MM/DD/YYYY HH:MI:SS PM') FROM DUAL
UNION ALL
SELECT TO_DATE ('5/9/2022 12:33:02 PM', 'MM/DD/YYYY HH:MI:SS PM') FROM DUAL
UNION ALL
SELECT TO_DATE ('5/9/2022 10:34:02 AM', 'MM/DD/YYYY HH:MI:SS PM') FROM DUAL
UNION ALL
SELECT TO_DATE ('5/9/2022 10:20:02 AM', 'MM/DD/YYYY HH:MI:SS PM') FROM DUAL
UNION ALL
SELECT TO_DATE ('5/9/2022 6:54:02 AM', 'MM/DD/YYYY HH:MI:SS PM') FROM DUAL
UNION ALL
SELECT TO_DATE ('5/9/2022 4:28:02 AM', 'MM/DD/YYYY HH:MI:SS PM') FROM DUAL
UNION ALL
SELECT TO_DATE ('5/9/2022 5:08:02 AM', 'MM/DD/YYYY HH:MI:SS PM') FROM DUAL)
SELECT TO_CHAR (dt, 'MM/DD/YYYY HH:MI:SS PM') AS dt,
TO_CHAR (nearest_hour, 'MM/DD/YYYY HH:MI:SS PM') AS nearest_hour
FROM (SELECT dt,
nearest_hour,
ROW_NUMBER () OVER (PARTITION BY nearest_hour ORDER BY time_from_hour) AS time_rank
FROM (SELECT dt,
CASE
WHEN dt - TRUNC (dt, 'HH') <
ABS ((TRUNC (dt, 'HH') + INTERVAL '1' HOUR) - dt)
THEN
TRUNC (dt, 'HH')
ELSE
TRUNC (dt, 'HH') + INTERVAL '1' HOUR
END AS nearest_hour,
LEAST (dt - TRUNC (dt, 'HH'),
ABS ((TRUNC (dt, 'HH') + INTERVAL '1' HOUR) - dt)) AS time_from_hour
FROM sample_dates))
WHERE time_rank = 1
ORDER BY 1;
Result
DT NEAREST_HOUR
_________________________ _________________________
05/09/2022 02:32:02 AM 05/09/2022 03:00:00 AM
05/09/2022 04:28:02 AM 05/09/2022 04:00:00 AM
05/09/2022 05:08:02 AM 05/09/2022 05:00:00 AM
05/09/2022 06:54:02 AM 05/09/2022 07:00:00 AM
05/09/2022 10:20:02 AM 05/09/2022 10:00:00 AM
05/09/2022 10:34:02 AM 05/09/2022 11:00:00 AM
05/09/2022 12:33:02 PM 05/09/2022 01:00:00 PM
To get the closest row to a particular hour on any day then, from Oracle 12, you can use:
SELECT *
FROM table_name
ORDER BY ABS(
TRUNC(yourDate) + INTERVAL '07:00:00' HOUR TO SECOND
- yourDate
)
FETCH FIRST ROW ONLY;
Which, for the sample data:
CREATE TABLE table_name (id, yourDate) AS
SELECT 1, DATE '2022-05-09' + INTERVAL '02:32:02' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 2, DATE '2022-05-09' + INTERVAL '12:33:02' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 3, DATE '2022-05-09' + INTERVAL '10:34:02' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 4, DATE '2022-05-09' + INTERVAL '10:20:02' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 5, DATE '2022-05-09' + INTERVAL '06:54:02' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 6, DATE '2022-05-09' + INTERVAL '04:28:02' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 7, DATE '2022-05-09' + INTERVAL '05:08:02' HOUR TO SECOND FROM DUAL;
Outputs:
ID
YOURDATE
5
2022-05-09 06:54:02
If you want the closest hour to each of your rows then:
SELECT t.*,
TRUNC(yourDate, 'HH') + ROUND((yourDate - TRUNC(yourDate, 'HH'))*24)/24
AS nearest_hour
FROM table_name t
Outputs:
ID
YOURDATE
NEAREST_HOUR
1
2022-05-09 02:32:02
2022-05-09 03:00:00
2
2022-05-09 12:33:02
2022-05-09 13:00:00
3
2022-05-09 10:34:02
2022-05-09 11:00:00
4
2022-05-09 10:20:02
2022-05-09 10:00:00
5
2022-05-09 06:54:02
2022-05-09 07:00:00
6
2022-05-09 04:28:02
2022-05-09 04:00:00
7
2022-05-09 05:08:02
2022-05-09 05:00:00
If, for each closest hour, you want the single closest row then:
SELECT *
FROM (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY nearest_hour ORDER BY ABS(nearest_hour - yourDate))
AS rn
FROM (
SELECT t.*,
TRUNC(yourDate, 'HH') + ROUND((yourDate - TRUNC(yourDate, 'HH'))*24)/24
AS nearest_hour
FROM table_name t
) t
)
WHERE rn = 1
Outputs:
ID
YOURDATE
NEAREST_HOUR
RN
1
2022-05-09 02:32:02
2022-05-09 03:00:00
1
6
2022-05-09 04:28:02
2022-05-09 04:00:00
1
7
2022-05-09 05:08:02
2022-05-09 05:00:00
1
5
2022-05-09 06:54:02
2022-05-09 07:00:00
1
4
2022-05-09 10:20:02
2022-05-09 10:00:00
1
3
2022-05-09 10:34:02
2022-05-09 11:00:00
1
2
2022-05-09 12:33:02
2022-05-09 13:00:00
1
db<>fiddle here
I have one requirement where I have to show the records between specific date and time every day in one week duration.
in one week duration( 2019-04-01 till 2019-04-06) ,for instance record of 2019-04-01 at 19 PM till 8 Am of 2019-04-02 ,and record of 2019-04-02 at 19 PM till 08 AM of 2019-04-03 and ...
would you please help me!
Use recursive query to create proper periods then join with your data or do it simpler with condition like here:
select callbegin, callerno
from table4
where callerno in ('7032','750')
and callbegin between timestamp '2019-04-01 19:00:00'
and timestamp '2019-04-06 08:00:00'
and ('19' <= to_char(callbegin, 'hh24') or to_char(callbegin, 'hh24') < '08');
demo
Here's how I understood the question.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi';
Session altered.
SQL> break on period;
SQL> with
2 data (id, datum) as
3 (select 1, to_date('01.04.2019 15:30', 'dd.mm.yyyy hh24:mi') from dual union all
4 select 2, to_date('01.04.2019 20:00', 'dd.mm.yyyy hh24:mi') from dual union all -- 1st
5 select 3, to_date('02.04.2019 01:15', 'dd.mm.yyyy hh24:mi') from dual union all -- 1st perios
6 select 4, to_date('02.04.2019 11:00', 'dd.mm.yyyy hh24:mi') from dual union all
7 select 5, to_date('02.04.2019 23:15', 'dd.mm.yyyy hh24:mi') from dual union all -- 2nd period
8 select 6, to_date('03.04.2019 00:10', 'dd.mm.yyyy hh24:mi') from dual union all -- 2nd
9 select 7, to_date('04.04.2019 22:20', 'dd.mm.yyyy hh24:mi') from dual -- 3rd period
10 ),
11 test as
12 (select date '2019-04-01' dstart,
13 date '2019-04-06' dend
14 from dual
15 ),
16 inter as
17 (select dstart + level - 1 datum
18 from test
19 connect by level <= dend - dstart + 1
20 ),
21 from_to as
22 (select datum + 19/24 date_from,
23 lead(datum) over (order by datum) + 8/24 date_to
24 from inter
25 )
26 select f.date_From ||' - '|| f.date_to period,
27 d.id,
28 d.datum
29 from data d join from_to f on 1 = 1
30 where d.datum between f.date_from and f.date_to
31 order by f.date_From, d.id;
PERIOD ID DATUM
----------------------------------- ---------- ----------------
01.04.2019 19:00 - 02.04.2019 08:00 2 01.04.2019 20:00
3 02.04.2019 01:15
02.04.2019 19:00 - 03.04.2019 08:00 5 02.04.2019 23:15
6 03.04.2019 00:10
04.04.2019 19:00 - 05.04.2019 08:00 7 04.04.2019 22:20
SQL>
This is how to filter data by days and time by one week:
With date_list as (
Select
to_date(to_char( (sysdate - level), 'yyyymmdd') || '19', 'yyyymmddhh24') begin_time,
to_date(to_char( ((sysdate - level)+1), 'yyyymmdd') || '08', 'yyyymmddhh24') end_time
From dual connect by level <= 7
)
Select begin_time, your_table.*
From
your_table t1,
date_list t2
Where
t1.your_date between t2.begin_time and t2.end_time;
I have an oracle query which returns next mont first sunday.
now i have a condition here to check if the date which has passed is first sunday of current month, then we need second sunday in current month.
Else, next month first sunday.
My query:
DEF startDate = to_date('somedate', 'dd/mm/yyyy');
Select next_day(last_day(&startDate),'Sunday' ) from dual ;
Expected output:
if we input 1st july 2018, it has to return 8th july 2018(second sunday) else, any other day apart from first sunday like, (2nd july 2018), it has to return 5th Aug 2018.
Input Expected Output
01-Jul-18 08-Jul-18,
02-Jul-18 05-Aug-18,
05-Aug-18 12-Aug-18,
19-Aug-18 02-Sep-18.
Based on the description in your question and comments you want something like:
case when start_date = next_day(trunc(start_date, 'MM') - 1, 'Sunday') -- date is on first sunday
then next_day(start_date, 'Sunday') -- next Sunday, which is second in month
else next_day(last_day(start_date), 'Sunday') -- first Sunday of next month
end
With some sample dates in a CTE, including some discussed but also others:
with cte (start_date) as (
select date '2018-05-30' from dual
union all select date '2018-06-01' from dual
union all select date '2018-06-02' from dual
union all select date '2018-06-03' from dual
union all select date '2018-06-04' from dual
union all select date '2018-06-30' from dual
union all select date '2018-07-01' from dual
union all select date '2018-07-02' from dual
union all select date '2018-07-03' from dual
union all select date '2018-07-04' from dual
union all select date '2018-07-05' from dual
union all select date '2018-07-06' from dual
union all select date '2018-07-07' from dual
union all select date '2018-07-08' from dual
union all select date '2018-07-31' from dual
union all select date '2018-08-01' from dual
union all select date '2018-08-02' from dual
union all select date '2018-08-03' from dual
union all select date '2018-08-04' from dual
union all select date '2018-08-05' from dual
union all select date '2018-08-06' from dual
)
select start_date,
to_char(start_date, 'Dy') as day,
case when to_char(start_date, 'Dy') = 'Sun'
then 'Yes' else 'No' end as is_sunday,
case when start_date = next_day(trunc(start_date, 'MM') - 1, 'Sunday')
then 'Yes' else 'No' end as is_first_sunday,
next_day(trunc(start_date, 'MM') - 1, 'Sunday') as first_sun_this_month,
next_day(trunc(start_date, 'MM') + 6, 'Sunday') as second_sun_this_month,
next_day(last_day(start_date), 'Sunday') as first_sun_next_month,
case when start_date = next_day(trunc(start_date, 'MM') - 1, 'Sunday') -- date is on first sunday
then next_day(start_date, 'Sunday') -- next Sunday, which is second in month
else next_day(last_day(start_date), 'Sunday') -- first Sunday of next month
end as result
from cte;
gets
START_DATE DAY IS_ IS_ FIRST_SUN_ SECOND_SUN FIRST_SUN_ RESULT
---------- ------------ --- --- ---------- ---------- ---------- ----------
2018-05-30 Wed No No 2018-05-06 2018-05-13 2018-06-03 2018-06-03
2018-06-01 Fri No No 2018-06-03 2018-06-10 2018-07-01 2018-07-01
2018-06-02 Sat No No 2018-06-03 2018-06-10 2018-07-01 2018-07-01
2018-06-03 Sun Yes Yes 2018-06-03 2018-06-10 2018-07-01 2018-06-10
2018-06-04 Mon No No 2018-06-03 2018-06-10 2018-07-01 2018-07-01
2018-06-30 Sat No No 2018-06-03 2018-06-10 2018-07-01 2018-07-01
2018-07-01 Sun Yes Yes 2018-07-01 2018-07-08 2018-08-05 2018-07-08
2018-07-02 Mon No No 2018-07-01 2018-07-08 2018-08-05 2018-08-05
2018-07-03 Tue No No 2018-07-01 2018-07-08 2018-08-05 2018-08-05
2018-07-04 Wed No No 2018-07-01 2018-07-08 2018-08-05 2018-08-05
2018-07-05 Thu No No 2018-07-01 2018-07-08 2018-08-05 2018-08-05
2018-07-06 Fri No No 2018-07-01 2018-07-08 2018-08-05 2018-08-05
2018-07-07 Sat No No 2018-07-01 2018-07-08 2018-08-05 2018-08-05
2018-07-08 Sun Yes No 2018-07-01 2018-07-08 2018-08-05 2018-08-05
2018-07-31 Tue No No 2018-07-01 2018-07-08 2018-08-05 2018-08-05
2018-08-01 Wed No No 2018-08-05 2018-08-12 2018-09-02 2018-09-02
2018-08-02 Thu No No 2018-08-05 2018-08-12 2018-09-02 2018-09-02
2018-08-03 Fri No No 2018-08-05 2018-08-12 2018-09-02 2018-09-02
2018-08-04 Sat No No 2018-08-05 2018-08-12 2018-09-02 2018-09-02
2018-08-05 Sun Yes Yes 2018-08-05 2018-08-12 2018-09-02 2018-08-12
2018-08-06 Mon No No 2018-08-05 2018-08-12 2018-09-02 2018-09-02
The result column is the one you're interested in, the others just try to show the working a bit.
It looks odd to have the result dates out of sequence compared to the input dates - 2018-06-03 going to 2018--06-10 then those both before and after it go to 2018-07-01. But that seems to be what you want.
I have a query that gives me renders per minute (when there is a render during the minute)
select count(*) as "Total Rendered", to_char(r.request_dt, 'YYYY-MM-DD HH24:MI') as "ByMinute" from form_render r where r.form_type_id = 49
and r.request_dt >= to_timestamp('09-16-2015 08:00', 'mm-dd-yyyy hh24:mi')
group by to_char(r.request_dt, 'YYYY-MM-DD HH24:MI')
order by to_char(r.request_dt, 'YYYY-MM-DD HH24:MI') desc
Total Rendered | ByMinute
19 2015-09-17 09:31
10 2015-09-17 09:30
1 2015-09-17 09:28
6 2015-09-17 09:27
18 2015-09-17 09:25
22 2015-09-17 09:24
12 2015-09-17 09:23
13 2015-09-17 09:21
22 2015-09-17 09:20
However I want a row for all times (by minute) even when there were none rendered (add rows for times when no renders occurred...09:22,09:26, 09:29)
So something like this
Total Rendered | ByMinute
19 2015-09-17 09:31
10 2015-09-17 09:30
0 2015-09-17 09:29
1 2015-09-17 09:28
6 2015-09-17 09:27
0 2015-09-17 09:26
18 2015-09-17 09:25
22 2015-09-17 09:24
12 2015-09-17 09:23
0 2015-09-17 09:22
13 2015-09-17 09:21
22 2015-09-17 09:20
Any help is greatly appreciated
Sean
===========================================================================
Sept 20 attempt.....
===========================================================================
Thank you very much for taking the time to put this together. SQL is definitely not my strength as I am sure you can tell!
So I have patched together the time table and my query but am getting an error (ORA01843: not a valid month.)
When I run my query by itself
select count(*)as "Total_Rendered" , to_char(r.request_dt, 'MM/DD/YYYY HH24:MI')as "ByMinute" from form_render r where r.form_type_id = 49
and r.request_dt >= to_timestamp('09/17/2015 09:11', 'mm/dd/yyyy hh24:mi') and r.request_dt <= to_timestamp('09/17/2015 09:18', 'mm/dd/yyyy hh24:mi')
group by to_char(r.request_dt, 'MM/DD/YYYY HH24:MI')
order by 2 desc
I get the following
TOTAL_RENDERED | ByMinute
---------------------------
4 | 09/17/2015 09:18
16 | 09/17/2015 09:17
4 | 09/17/2015 09:16
2 | 09/17/2015 09:11
When I run the minute_table query
WITH min_date AS /* replace start and stop timestamp here */
(SELECT to_date('09/17/2015 09:11', 'MM/DD/YYYY hh24:mi') minute FROM dual
),
max_date AS
(SELECT to_date('09/17/2015 09:18', 'MM/DD/YYYY hh24:mi') minute FROM dual
),
minute_table AS
(SELECT
(SELECT minute FROM min_date
) + (rownum -1)/(24*60) AS by_minute
FROM dual
CONNECT BY level <=
(SELECT (24*60) *(
(SELECT minute FROM max_date
) -
(SELECT minute FROM min_date
))+1
FROM dual
)
)
select * from minute_table
I get the following....
9/17/2015 9:11:00 AM
9/17/2015 9:12:00 AM
9/17/2015 9:13:00 AM
9/17/2015 9:14:00 AM
9/17/2015 9:15:00 AM
9/17/2015 9:16:00 AM
9/17/2015 9:17:00 AM
9/17/2015 9:18:00 AM
so far so good.
When I combine the two queries to get this query
WITH min_date AS /* replace start and stop timestamp here */
(SELECT to_date('09/17/2015 09:11', 'MM/DD/YYYY hh24:mi:ss') minute FROM dual
),
max_date AS
(SELECT to_date('09/17/2015 09:18', 'MM/DD/YYYY hh24:mi:ss') minute FROM dual
),
minute_table AS
(SELECT
(SELECT minute FROM min_date
) + (rownum -1)/(24*60) AS by_minute
FROM dual
CONNECT BY level <=
(SELECT (24*60) *(
(SELECT minute FROM max_date
) -
(SELECT minute FROM min_date
))+1
FROM dual
)
),
tbl AS
(
select count(*)as "Total_Rendered" , to_char(r.request_dt, 'MM/DD/YYYY HH24:MI')as "ByMinute" from form_render r where r.form_type_id = 49
and r.request_dt >= to_timestamp('09/17/2015 09:11', 'mm/dd/yyyy hh24:mi') and r.request_dt <= to_timestamp('09/17/2015 09:18', 'mm/dd/yyyy hh24:mi')
group by to_char(r.request_dt, 'MM/DD/YYYY HH24:MI')
order by 2 desc
)
SELECT minute_table.by_minute ,
NVL(tbl."Total_Rendered",'0') AS total_rendered
FROM minute_table
left OUTER JOIN tbl
ON tbl."ByMinute" = minute_table.by_minute
order by 1 desc
;
I get an error ORA01843: not a valid month.
I am not entirely certain why the error is occuring but I am confident it has to do with the format differences between the columns I am joining on?
The format of the dates in the time table vs my table are likely the cause but I am not certain.
Time Table has 9/17/2015 9:11:00 AM and
my query has 09/17/2015 09:11 (notice missing leading zero on Month, seconds and AM)
Any help is appreciated.
Thanks again for your time and expertise....
Sean
Slightly different solution without dependency on 12c and with "parameters" for start and stop minutes.
WITH min_date AS /* replace start and stop timestamp here */
(SELECT to_date('2015-09-17 09:28','yyyy-mm-dd hh24:mi') minute FROM dual
),
max_date AS
(SELECT to_date('2015-09-17 09:31','yyyy-mm-dd hh24:mi') minute FROM dual
),
minute_table AS
(SELECT
(SELECT minute FROM min_date
) + (rownum -1)/(24*60) AS by_minute
FROM dual
CONNECT BY level <=
(SELECT (24*60) *(
(SELECT minute FROM max_date
) -
(SELECT minute FROM min_date
))+1
FROM dual
)
),
tbl AS
(SELECT 19 Total_Rendered,
to_date('2015-09-17 09:31','YYYY-MM-DD HH24:MI') By_Minute
FROM dual
UNION ALL
SELECT 1,to_date('2015-09-17 09:30','YYYY-MM-DD HH24:MI') FROM dual
UNION ALL
SELECT 19,to_date('2015-09-17 09:28','YYYY-MM-DD HH24:MI') FROM dual
)
SELECT minute_table.by_minute ,
NVL(tbl.total_rendered,'0') AS total_rendered
FROM minute_table
LEFT OUTER JOIN tbl
ON tbl.By_Minute = minute_table.by_minute
;
So this is working in Oracle 12c. But you have to change it for your use.
with tbl(Total_Rendered, ByMinute) as (
select 19,to_date('2015-09-17 09:31','YYYY-MM-DD HH24:MI') from dual union all
select 1,to_date('2015-09-17 09:30','YYYY-MM-DD HH24:MI') from dual union all
select 19,to_date('2015-09-17 09:28','YYYY-MM-DD HH24:MI') from dual )
select nvl(tbl.total_rendered,'0') as total_rendered,by_minute from
(select to_date('2015-09-17 09:28','YYYY-MM-DD HH24:MI') + (1/24/60) * column_value as by_minute from
TABLE( CAST( MULTISET( SELECT LEVEL FROM DUAL
CONNECT BY LEVEL <= 3 ) AS SYS.ODCINUMBERLIST
) )) time_range
left outer join
tbl
on tbl.ByMinute = time_range.by_minute
Output
TOTAL_RENDERED BY_MINUTE
0 17-SEP-2015 09:29:00
1 17-SEP-2015 09:30:00
19 17-SEP-2015 09:31:00
What I did is first I am using a temporary table tbl which will have data as your input. Then I generated timestamp from '17-SEP-2015 09:29:00' - '17-SEP-2015 09:31:00'to generate a time_range
Now I did a left outer join from this time_range to tbl which has missing data. For the rows not in tbl, I am printing 0.
You can use this query and edit it to get the time_range and join with your data to get this output.
I have a requirement to show 1 to 20 questions how many teams answered for 0-23 hours. The table structure
Team_id Question_id Updated
124 25092 02-SEP-14 11:30:12 AM
15 25076 02-SEP-14 02:31:15 PM
258 25061 02-SEP-14 03:02:33 PM
298 25196 02-SEP-14 03:32:49 PM
450 25203 02-SEP-14 07:01:05 PM
471 25351 02-SEP-14 07:47:31 PM
482 25350 02-SEP-14 08:01:03 PM
78 24924 02-SEP-14 08:01:29 PM
541 26032 02-SEP-14 09:35:00 PM
708 26485 02-SEP-14 12:19:48 PM
726 26125 02-SEP-14 01:00:11 PM
145 26221 02-SEP-14 03:45:32 PM
824 26436 02-SEP-14 06:30:16 PM
87 26505 02-SEP-14 06:30:22 PM
825 26488 02-SEP-14 06:31:34 PM
466 26488 02-SEP-14 06:34:48 PM
868 26091 02-SEP-14 08:30:59 PM
1356 28852 02-SEP-14 07:45:14 PM
1342 28852 02-SEP-14 07:45:27 PM
Query should return
Hours 1 2 3 4 5 to 20
10 6 0 2 3 6 to 25
11 3 2 1 1 7 to 300
12 2 0 5 0 7 to 30
13 1 6 1 1 7 to 40
these are count of team that answered only 1 question in hour 10
these are count of team that answered only 2 question in hour 10 etc.
Note it is not 1st or 2nd question.
Thanks
Arun
You need something like this I suppose:
select hour,
count(decode(cnt, 1, 1)) as q1,
count(decode(cnt, 2, 1)) as q2,
count(decode(cnt, 3, 1)) as q3,
count(decode(cnt, 4, 1)) as q4,
...
count(decode(cnt, 20, 1)) as q20
from (
select to_char(updated, 'HH24') as hour
, count(*) as cnt
from &table_name
group by to_char(updated, 'HH24'), team_id
)
group by hour;
As far as I understand, perhaps you want something like this :
SQL> WITH DATA AS(
2 SELECT 124 team_id, 25092 question_id, to_date('02-SEP-14 11:30:12 AM','DD-MON-RR HH:MI:SS AM') UPDATED FROM DUAL UNION ALL
3 SELECT 15 , 25076 ,to_date('02-SEP-14 02:31:15 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
4 SELECT 258 , 25061 ,to_date('02-SEP-14 03:02:33 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
5 SELECT 298 , 25196 ,to_date('02-SEP-14 03:32:49 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
6 SELECT 450 , 25203 ,to_date('02-SEP-14 07:01:05 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
7 SELECT 471 , 25351 ,to_date('02-SEP-14 07:47:31 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
8 SELECT 482 , 25350 ,to_date('02-SEP-14 08:01:03 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
9 SELECT 78 , 24924 ,to_date('02-SEP-14 08:01:29 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
10 SELECT 541 , 26032 ,to_date('02-SEP-14 09:35:00 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
11 SELECT 708 , 26485 ,to_date('02-SEP-14 12:19:48 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
12 SELECT 726 , 26125 ,to_date('02-SEP-14 01:00:11 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
13 SELECT 145 , 26221 ,to_date('02-SEP-14 03:45:32 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
14 SELECT 824 , 26436 ,to_date('02-SEP-14 06:30:16 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
15 SELECT 87 , 26505 ,to_date('02-SEP-14 06:30:22 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
16 SELECT 825 , 26488 ,to_date('02-SEP-14 06:31:34 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
17 SELECT 466 , 26488 ,to_date('02-SEP-14 06:34:48 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
18 SELECT 868 , 26091 ,to_date('02-SEP-14 08:30:59 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
19 SELECT 1356 , 28852 ,to_date('02-SEP-14 07:45:14 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
20 SELECT 1342 , 28852 ,to_date('02-SEP-14 07:45:27 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL)
21 SELECT 5 hours,
22 COUNT(team_id)
23 FROM DATA
24 WHERE UPDATED BETWEEN to_date('02-SEP-14 10:00:01','DD-MON-RR HH24:MI:SS') AND to_date('02-SEP-14 14:59:59','DD-MON-RR HH24:MI:SS')
25 UNION
26 SELECT 6 hours,
27 COUNT(team_id)
28 FROM DATA
29 WHERE UPDATED BETWEEN to_date('02-SEP-14 10:00:01','DD-MON-RR HH24:MI:SS') AND to_date('02-SEP-14 15:59:59','DD-MON-RR HH24:MI:SS')
30 UNION
31 SELECT 10 hours,
32 COUNT(team_id)
33 FROM DATA
34 WHERE UPDATED BETWEEN to_date('02-SEP-14 10:00:01','DD-MON-RR HH24:MI:SS') AND to_date('02-SEP-14 19:59:59','DD-MON-RR HH24:MI:SS')
35 UNION
36 SELECT 24 hours,
37 COUNT(team_id)
38 FROM DATA
39 WHERE UPDATED BETWEEN to_date('02-SEP-14 00:00:01','DD-MON-RR HH24:MI:SS') AND to_date('02-SEP-14 23:59:59','DD-MON-RR HH24:MI:SS')
40 /
HOURS COUNT(TEAM_ID)
---------- --------------
5 4
6 7
10 15
24 19
The time interval as an example, I took varying intervals, and the HOURS column is the time interval mentioned in the WHERE clause.