简体   繁体   中英

Oracle SQL: to count the records based on fixed time frame (say 15 or 30 minutes)

I have a table similar to

Start time            |       End Time                 | User |
09/02/2021 03:01:13   |       09/02/2021 03:45:15      | ABC  |
09/02/2021 03:15:20   |       09/02/2021 05:03:20      | XYZ  |
09/02/2021 06:03:12   |       09/02/2021 06:15:30      | DEF  |

Expecting output:

StDt                  |       EndDt                    | Count(1) 
09/02/2021 00:00:00   |       09/02/2021 01:00:00      | 0
09/02/2021 01:00:00   |       09/02/2021 02:00:00      | 0
09/02/2021 02:00:00   |       09/02/2021 03:00:00      | 0
09/02/2021 03:00:00   |       09/02/2021 04:00:00      | 2
09/02/2021 04:00:00   |       09/02/2021 05:00:00      | 1
09/02/2021 05:00:00   |       09/02/2021 06:00:00      | 0
09/02/2021 06:00:00   |       09/02/2021 07:00:00      | 1

The interval in this example is hourly but i would like to keep it flexible for 10 mins/15 mins/30 mins. I want this to be written in single sql. All i could work out till now is how to generate the range.

select t1.StartDt, t1.EndDt from 
(
  select 
    (to_char(timestamp '2021-02-09 00:00:00' + numtodsinterval(rownum*60,'MINUTE') - numtodsinterval(60,'MINUTE'),'DD-MM-YYYY hh24:mi')) as StartDt,
    (to_char(timestamp '2021-02-09 00:00:00' + numtodsinterval(rownum*60,'MINUTE'),'DD-MM-YYYY hh24:mi')) as EndDt
  from dual connect by level <= 24
) t1;

I dont know how to link to the table mentioned above to get the data in the format i require.

You have such a nice startup, except keep the timestamp format for the time values within the subquery, and move TO_CHAR formatting to the main query at the result displaying phase along with using correlated subquery with distinctly count aggregation for the overlapping intervals, and use bind variables as the placeholder for the time portion values( 60 , 30 , 15 ) such as

SQL> var min number
SQL> exec :min := 60
 
PL/SQL procedure successfully completed
min
---------
60
 
SQL> SELECT TO_CHAR(t.StartDt,'DD-MM-YYYY HH24:MI') AS StartDt,
  2         TO_CHAR(t.EndDt,'DD-MM-YYYY HH24:MI') AS EndDt,
  3         ( SELECT COUNT(DISTINCT "User") 
                FROM tab 
               WHERE t.EndDt >= Start_Time 
                 AND t.StartDt <= End_Time ) AS Count
  4    FROM
  5    (
  6       SELECT timestamp '2021-02-09 00:00:00' +
  7                        numtodsinterval(rownum * :min, 'MINUTE') -
  8                        numtodsinterval(:min, 'MINUTE') AS StartDt,
  9              timestamp '2021-02-09 00:00:00' +
 10                        numtodsinterval(rownum * :min, 'MINUTE') AS EndDt
 11         FROM dual
 12      CONNECT BY level <= 24
 13    ) t
 14   ORDER BY StartDt;
 
STARTDT          ENDDT                 COUNT
---------------- ---------------- ----------
09-02-2021 00:00 09-02-2021 01:00          0
09-02-2021 01:00 09-02-2021 02:00          0
09-02-2021 02:00 09-02-2021 03:00          0
09-02-2021 03:00 09-02-2021 04:00          2
09-02-2021 04:00 09-02-2021 05:00          1
09-02-2021 05:00 09-02-2021 06:00          1
09-02-2021 06:00 09-02-2021 07:00          1
09-02-2021 07:00 09-02-2021 08:00          0
.....
.....

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM