SQL:如果某行不存在,则返回该行的“0”

SQL:如果某行不存在,则返回该行的“0”,sql,oracle,Sql,Oracle,我有一个显示计数、日期和时间的SQL查询 这是输出的样子: 这是我的SQL查询: select count(*), to_char(timestamp, 'MM/DD/YYYY'), to_char(timestamp, 'HH24') from MY_TABLE where timestamp >= to_timestamp('03/01/2016','MM/DD/YYYY') group by to_char(timestam

我有一个显示计数、日期和时间的SQL查询

这是输出的样子:

这是我的SQL查询:

select 
    count(*), 
    to_char(timestamp, 'MM/DD/YYYY'), 
    to_char(timestamp, 'HH24')
from 
    MY_TABLE
where 
    timestamp >= to_timestamp('03/01/2016','MM/DD/YYYY')
group by 
    to_char(timestamp, 'MM/DD/YYYY'), to_char(timestamp, 'HH24') 
现在,在计数列中,如果该小时的计数不存在,我想显示0。因此,2016年3月2日上午8点,计数为6。然后在上午9点,计数为0,因此该行没有显示。我想显示那一行。在上午10点和11点,计数会显示出来,然后就转到第二天

那么如何显示0的计数?我想每天显示0个计数,每小时显示0或6或其他值都无关紧要。谢谢:

使用cte生成一天中所有小时的数字。然后将结果与表中所有可能的日期交叉连接。然后在具有所有日期和小时组合的cte上左键联接,当某一行在特定的小时内不存在时,得到0计数

with nums(n) as (select 1 from dual
                 union all 
                 select n+1 from nums where n < 24)
,dateshrscomb as (select n,dt 
                   from nums 
                   cross join (select distinct trunc(timestamp) dt from my_table 
                               where timestamp >= to_timestamp('03/01/2016','MM/DD/YYYY')
                               ) alldates
                   )
select count(trunc(m.timestamp)), d.dt, d.n
from dateshrscomb d
left join MY_TABLE m on to_char(m.timestamp, 'HH24') = d.n  
and trunc(m.timestamp) = d.dt
and m.timestamp >= to_timestamp('03/01/2016','MM/DD/YYYY')
group by d.dt, d.n

@VPK在回答方面做得很好,我只是碰巧在他上次编辑生成日期小时交叉连接的同时写了这篇文章。此解决方案与his的不同之处在于,它将获取所需最大值和最小值之间的所有日期。其中his将仅获取表中的日期,因此,如果您完全缺少一天,则his中不会显示该日期,而会显示在该日期中。另外,我还对连接进行了一些清理。

这里有一种方法

使用Oracle的分层查询功能和级别psuedo列,生成日期和小时数。 然后用你的数据做上面的外部连接。 需要根据所需的范围调整级别的值。本例使用120。开始日期也需要设置。在本例中,它是truncsysdate,'hh24'-2/24

select nvl(c1.cnt, 0), d1.date_part, d1.hour_part
from
(
    select
      to_char(s.dt - (c.lev)/24, 'mm/dd/yyyy') date_part, 
      to_char(s.dt - (c.lev)/24, 'hh24') hour_part
    from
      (select level lev from dual connect by level <= 120) c,
      (select trunc(sysdate, 'hh24')-2/24 dt from dual) s
    where (s.dt - (c.lev)/24) < trunc(sysdate, 'hh24')-2/24
) d1
full outer join
(
    select 
        count(*) cnt, 
        to_char(timestamp, 'MM/DD/YYYY') date_part, 
        to_char(timestamp, 'HH24') hour_part
    from 
        MY_TABLE
    where 
        timestamp >= to_timestamp('03/01/2016','MM/DD/YYYY')
    group by 
        to_char(timestamp, 'MM/DD/YYYY'), to_char(timestamp, 'HH24') 
) c1
on d1.date_part = c1.date_part
and d1.hour_part = c1.hour_part

使用分区外部联接:

SELECT m.day,
       h.hr,
       COALESCE( freq, 0 ) AS freq
FROM   ( SELECT LEVEL - 1 AS hr
         FROM   DUAL
         CONNECT BY LEVEL <= 24
       ) h
       LEFT OUTER JOIN
       ( SELECT COUNT(*) AS freq,
                TO_CHAR( "timestamp", 'mm/dd/yyyy' ) AS day,
                EXTRACT( HOUR FROM "timestamp" ) AS hr
         FROM   MY_TABLE 
         WHERE  "timestamp" >= TIMESTAMP '2016-03-01 00:00:00'
         GROUP BY
                TO_CHAR( "timestamp", 'mm/dd/yyyy' ),
                EXTRACT( HOUR FROM "timestamp" )
       ) m
       PARTITION BY ( m.day, m.hr )
       ON ( m.hr = h.hr );

这是Oracle,不是MySQL。像他这样的Sorrylooks可能也需要日期部分,尽管他有多天的时间,否则他怎么知道2016年3月2日他错过了上午9点,但3月3日他错过了6点PM@vkp,谢谢你的回复,我试过了,但仍然得到了相同的结果。我在第8行m*上遇到了一个错误。错误是:user.table.column、table.column或column规范无效我看到了..将其更改为countm.somecolumnname..我也编辑了答案谢谢,您的答案工作正常。然而,我看到了2011年的结果。如果时间戳>=添加到时间戳'03/01/2016'、'MM/DD/YYYY'中,我应该在哪里添加这行代码,以便我只能在特定日期后看到结果?
SELECT m.day,
       h.hr,
       COALESCE( freq, 0 ) AS freq
FROM   ( SELECT LEVEL - 1 AS hr
         FROM   DUAL
         CONNECT BY LEVEL <= 24
       ) h
       LEFT OUTER JOIN
       ( SELECT COUNT(*) AS freq,
                TO_CHAR( "timestamp", 'mm/dd/yyyy' ) AS day,
                EXTRACT( HOUR FROM "timestamp" ) AS hr
         FROM   MY_TABLE 
         WHERE  "timestamp" >= TIMESTAMP '2016-03-01 00:00:00'
         GROUP BY
                TO_CHAR( "timestamp", 'mm/dd/yyyy' ),
                EXTRACT( HOUR FROM "timestamp" )
       ) m
       PARTITION BY ( m.day, m.hr )
       ON ( m.hr = h.hr );