计数记录并按小时分组

时间:2019-01-26 04:11:08

标签: sql oracle oracle11g

我正在尝试对表中的记录进行计数,并按小时对它们进行分组,我在查询中获得结果,但是我希望它每小时返回一次,即使没有记录也是如此。

我当前的查询是

SELECT nvl(count(*),0) AS transactioncount, trunc(date_modified, 'HH') as TRANSACTIONDATE
FROM TABLE 
WHERE date_modified between to_date('23-JAN-19 07:00:00','dd-MON-yy hh24:mi:ss') and to_date('24-Jan-19 06:59:59','dd-MON-yy hh24:mi:ss') 
group by trunc(date_modified, 'HH');

这将返回这样的结果

TRANSACTIONCOUNT    |    TRANSACTIONDATE
      43            |   23-Jan-19 07:00:00
      47            |   23-Jan-19 08:00:00
      156           |   23-Jan-19 14:00:00
      558           |   23-Jan-19 15:00:00

我想要的是让它在我的两个约会之间每小时返回一次,

TRANSACTIONCOUNT    |    TRANSACTIONDATE
      43            |   23-Jan-19 07:00:00
      47            |   23-Jan-19 08:00:00
      0             |   23-Jan-19 09:00:00
      0             |   23-Jan-19 10:00:00
      0             |   23-Jan-19 11:00:00
      0             |   23-Jan-19 12:00:00
      0             |   23-Jan-19 13:00:00
      156           |   23-Jan-19 14:00:00
      558           |   23-Jan-19 15:00:00
  --......
      0             |   24-Jan-19 00:00:00
      0             |   24-Jan-19 01:00:00
      0             |   24-Jan-19 02:00:00
  --and so on

2 个答案:

答案 0 :(得分:2)

要填补交易时间内的漏洞,您首先要创建一个完整的小时表。

您可以使用Recursive Subquery Factoring来完成

WITH hour_table(TRANSACTIONDATE) AS (
   SELECT to_date('23-JAN-19 07:00:00','dd-MON-yy hh24:mi:ss') /* init hour here */
     FROM DUAL
  UNION ALL
   SELECT TRANSACTIONDATE + 1/24
     FROM hour_table
    WHERE TRANSACTIONDATE + 1/24 < to_date('24-JAN-19 06:59:59','dd-MON-yy hh24:mi:ss') /* limit here */
)
select * from hour_table;

TRANSACTIONDATE   
-------------------
23.01.2019 07:00:00 
23.01.2019 08:00:00 
... 
24.01.2019 05:00:00 
24.01.2019 06:00:00 

请注意,在此查询中使用的是开始日期和结束日期,开始日期必须精确到一个小时。

下一步很简单,就是将此小时表加入外部到您的汇总表,并使用NVL设置缺失小时数的默认值。

with hour_table(TRANSACTIONDATE) AS (
   SELECT to_date('23-JAN-19 07:00:00','dd-MON-yy hh24:mi:ss') /* init hour here */
     FROM DUAL
  UNION ALL
   SELECT TRANSACTIONDATE + 1/24
     FROM hour_table
    WHERE TRANSACTIONDATE + 1/24 < to_date('24-JAN-19 06:59:59','dd-MON-yy hh24:mi:ss') /* limit */
),
agg as (   
   SELECT nvl(count(*),0) AS transactioncount, trunc(date_modified, 'HH') as TRANSACTIONDATE
   FROM "TABLE" 
   WHERE date_modified between to_date('23-JAN-19 07:00:00','dd-MON-yy hh24:mi:ss') and to_date('24-Jan-19 06:59:59','dd-MON-yy hh24:mi:ss') 
   group by trunc(date_modified, 'HH')
)
select t.TRANSACTIONDATE, nvl(transactioncount,0) transactioncount
from hour_table t
left outer join agg a
on t.TRANSACTIONDATE = a.TRANSACTIONDATE
order by 1;

答案 1 :(得分:1)

您可以考虑将以下内容与CONNECT BY level逻辑结合使用:

SELECT sum(transactioncount) as transactioncount, transactiondate 
  FROM
  (
   with "TABLE"(date_modified) as
   (
     SELECT timestamp'2019-01-23 08:00:00' FROM dual union all
     SELECT timestamp'2019-01-23 08:30:00' FROM dual union all
     SELECT timestamp'2019-01-23 09:00:00' FROM dual union all
     SELECT timestamp'2019-01-24 05:01:00' FROM dual   
   )   
  SELECT nvl(count(*),0) AS transactioncount, trunc(date_modified, 'hh24') as transactiondate
    FROM "TABLE" t 
   GROUP BY trunc(date_modified, 'HH24')
  UNION ALL
  SELECT 0, timestamp'2019-01-23 07:00:00' + ( level - 1 )/24
    FROM dual    
 CONNECT BY level <=  24 * extract( day  from 
                            timestamp'2019-01-24 06:59:59'-
                            timestamp'2019-01-23 07:00:00') +
                           extract( hour from 
                            timestamp'2019-01-24 06:59:59'-
                            timestamp'2019-01-23 07:00:00') + 1      
)    
 GROUP BY transactiondate
 ORDER BY transactiondate

Rextester Demo