Oracle SQL。选择一年中每天的所有时间

时间:2015-10-16 21:24:41

标签: sql oracle

我尝试创建一个返回以下结果集的查询(为了便于阅读而被截断):

+---------------+-----------+--------+--------+----------+
| DATE_HAPPENED | Twelve_AM | One_AM | Two_AM | Three_AM | (and so on, until 24 hours)
+---------------+-----------+--------+--------+----------+
|  2015-10-01   |   110     |   34   |   92   |    45    |
+---------------+-----------+--------+--------+----------+

这是我使用的代码(我不确定它是最好的方法):

SELECT to_char(potty_use_date, 'yyyy-mm-dd HH12') as date_happened,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '12' THEN 1 ELSE 0 END) as Twelve_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '1' THEN 1 ELSE 0 END) as One_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '2' THEN 1 ELSE 0 END) as Two_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '3' THEN 1 ELSE 0 END) as Three_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '4' THEN 1 ELSE 0 END) as Four_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '5' THEN 1 ELSE 0 END) as Five_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '6' THEN 1 ELSE 0 END) as Six_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '7' THEN 1 ELSE 0 END) as Seven_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '8' THEN 1 ELSE 0 END) as Eight_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '9' THEN 1 ELSE 0 END) as Nine_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '10' THEN 1 ELSE 0 END) as Ten_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 AM') = '11' THEN 1 ELSE 0 END) as Eleven_AM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '1' THEN 1 ELSE 0 END) as One_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '2' THEN 1 ELSE 0 END) as Two_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '3' THEN 1 ELSE 0 END) as Three_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '4' THEN 1 ELSE 0 END) as Four_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '5' THEN 1 ELSE 0 END) as Five_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '6' THEN 1 ELSE 0 END) as Six_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '7' THEN 1 ELSE 0 END) as Seven_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '8' THEN 1 ELSE 0 END) as Eight_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '9' THEN 1 ELSE 0 END) as Nine_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '10' THEN 1 ELSE 0 END) as Ten_PM,
    COUNT(CASE WHEN to_char(potty_use_date, 'HH12 PM') = '11' THEN 1 ELSE 0 END) as Eleven_PM,
    CASE WHEN to_char(potty_use_date, 'HH12 PM') = '12' THEN 1 ELSE 0 END) as Twelve_PM
FROM core.potty_usage_statistics
GROUP BY to_char(potty_use_date, 'yyyy-mm-dd HH12')
ORDER BY date_happened ASC;        

但是,我得到了以下结果:

2015-04-20 08   1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197    1197

他们在结果窗口中全部重复。显然,我没有做到这一点。我该怎么做?

2 个答案:

答案 0 :(得分:2)

COUNT()计算非NULL值的数量。如果值为0或1,则所有值均为非NULL。因此,计数与COUNT(*)相同。

两个选项:

  • COUNT()更改为SUM()
  • 删除ELSE 0

就个人而言,我更喜欢第一种方法;但要么是可行的。

我还应该注意,您可以将EXTRACT()用于此目的:

SUM(CASE WHEN extract(hour from potty_use_date) = 0 THEN 1 ELSE 0 END) as Midnight,

有些人可能会觉得这更容易阅读。

我还怀疑您希望GROUP BYSELECT为:

SELECT to_char(potty_use_date, 'yyyy-mm-dd') as date_happened
. . .
GROUP BY to_char(potty_use_date, 'yyyy-mm-dd')

如果您包含小时组件,那么您将获得一个对角线值,每天24行,每个列都填充一小时列。

答案 1 :(得分:2)

也许你可以转动:

select * from 
(
  select
    trunc(p.potty_use_date) as potty_use_date,
    to_char(p.potty_use_date, 'HH24') as putty_use_hour,
  from
    core.potty_usage_statistics p
) 
pivot (
  count(putty_use_hour)
  for putty_use_hour in (
         '00' as "Midnight", '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', 
         '12' as "Noon", '13', '14', '15', '16', '17', '18' as "Dinner time", '19', '20', '21', '22', '23', '24' as "Or is this midnight")
)

我手头没有Oracle,所以我无法测试它,但这应该可行。

有关在Oracle中进行透视的详细信息,以及为什么需要整个小时列表的说明,请阅读SQL Operations: Pivot and Unpivot