给出以下声明,其中在表DATA中的给定时间(TIME)为用户(USER)注册任意事件:
CREATE TABLE DATA
(
"USER" Varchar(20),
"TIME" Time
);
INSERT INTO DATA ("USER", "TIME") VALUES ('Martin', '14:58:00.000');
INSERT INTO DATA ("USER", "TIME") VALUES ('Martin', '15:02:11.000');
INSERT INTO DATA ("USER", "TIME") VALUES ('Martin', '15:48:44.000');
INSERT INTO DATA ("USER", "TIME") VALUES ('Marion', '08:45:01.000');
INSERT INTO DATA ("USER", "TIME") VALUES ('Marion', '15:01:01.000');
INSERT INTO DATA ("USER", "TIME") VALUES ('Marion', '15:03:48.000');
在给定的一小时内找到每个用户的事件数量是微不足道的:
select
"USER",
extract(hour from "TIME") as "Hour",
count(*)
from
DATA
group by
"USER",
extract(hour from "TIME")
;
结果当然是:
USER |Hour|COUNT
------+----+-----
Marion| 8| 1
Marion| 15| 2
Martin| 14| 1
Martin| 15| 2
但是,如何以一小时的间隔获取每个用户一整天的事件数量?像这样:
USER |Hour|COUNT
------+----+-----
Marion| 0| 0
Marion| 1| 0
...
Marion| 7| 0
Marion| 8| 1
Marion| 9| 0
...
Marion| 14| 0
Marion| 15| 2
Marion| 16| 0
...
Marion| 22| 0
Marion| 23| 0
Martin| 0| 0
Martin| 1| 0
...
Martin| 13| 0
Martin| 14| 1
Martin| 15| 2
Martin| 16| 0
...
Martin| 22| 0
Martin| 23| 0
BTW我不会对所涉及的任何数据库进行写访问。
答案 0 :(得分:5)
你想要做这样的事情,创建一个数字为0到23的(临时)表HOURS,然后做一个外连接以获得所有的HOUR值,无论它们是否在DATA
select
"USER",
extract(hour from "TIME") as "Hour",
SUM(CASE WHEN Data.HOUR is NOT NULL 1 ELSE 0 END)
from
DATA
right outer join HOURS on extract(hour from "TIME") = HOURS.hour
group by
"USER",
extract(hour from "TIME")
;
如果你不能创建一个表,你可以做一些丑陋的事情,比如
(SELECT 1 as hour UNION 2 ... UNION 23) as HOURS
虽然根据你的方言可能有更好的方法来做到这一点
答案 1 :(得分:0)
@ spinning_plate的答案适用于垂直答案(两种方式 - 临时表或工会)
您可能也想要一个水平结果 - 即标题:user | 0000 | 0100 | 0200 | ...... | 2200 | 2300
如果是这样,那么有些选择......
使用SQL-Server 2005+或Oracle 11g +,查看PIVOT / UNPIVOT
使用Oracle< 11g,查看DECODE(例如:
SELECT
...
SUM(DECODE(extract(hour from "TIME"),1,1,0)) as 0100,
SUM(DECODE(extract(hour from "TIME"),13,1,0)) as 1300,
...