显示SELECT语句的结果,包括当天的每30分钟范围,当没有记录时填写0

时间:2017-11-22 16:23:19

标签: sql oracle

我有一张像这样的表arrivals

HHMM      Car
----      ---
0001      01
0001      02
0001      03
0002      04
...
0029      20
0029      21
0030      22
...
0059      56

我需要知道在30分钟的每个范围内有多少辆车到达。 我写了一个这样的查询:

WITH    

PREVIOUS_QUERIES AS
(
-- in fact, "PREVIOUS_QUERIES" represent a sequence of queries where I get 
-- the timestamp HHMM and convert it in a range where HOURS = HH and 
-- MINUTES_START can be 0 (if MM<30) or 30 (if MM>=30).
),

INTERVALS AS
(
SELECT
      TO_CHAR(HOURS,'FM00')||':'||TO_CHAR(MINUTES_START,'FM00')||' - '
        ||TO_CHAR(HOURS,'FM00')||':'||TO_CHAR(MINUTES_START +29,'FM00') AS INTERVAL,
    CAR

FROM
    PREVIOUS_QUERIES
)

SELECT
  INTERVAL, 
  COUNT (DISTINCT (CAR)),
  FROM INTERVALS
  GROUP BY INTERVAL
  ORDER BY INTERVAL
;

我的查询产生以下结果。

Interval        Cars
-------------   ----
00:00 - 00:29     21
00:30 - 00:59     35
01:00 - 01:29     41
02:30 - 02:59      5
03:00 - 03:29     12
03:30 - 03:59     13
...

这意味着,如果在某个时间间隔内没有到达,我的查询不会显示Cars = 0的行。我在结果中需要这些行:

01:30 - 01:59      0
02:00 - 02:29      0

我怎样才能添加这些行?可以通过更改我的查询来完成,或者 该查询是否应该完全重写?

我想象的是我应该从'00:00-00:29'到'23:30-23:59'生成30分钟的48个范围,然后将它们用作SELECT的参数,但我不知道我知道怎么做。

1 个答案:

答案 0 :(得分:0)

您可以将这48个值选择到另一个CTE中,例如'cteIntervals',然后将最终查询调整为:

SELECT
    I.Interval
    , NVL(Q.Cars, 0) Cars
FROM
    cteIntervals I
    LEFT JOIN
        (
            -- Your current query
        ) Q
    ON I.Interval = Q.Interval

这具有为最终查询创建模板的效果。

对于稍微更动态的解决方案,您可以考虑使用递归CTE生成cteIntervals,或者您可以将值存储在表等中。