cm0*_*007 6 join sql-server-2008-r2 group-by
我有以下架构:
CREATE TABLE Person (
PersonId int PRIMARY KEY
)
CREATE TABLE Action (
ActionId int PRIMARY KEY,
PersonId int NOT NULL FOREIGN KEY REFERENCES Person(PersonId),
ActionTime datetime NOT NULL
)
Run Code Online (Sandbox Code Playgroud)
以及以下数据:
INSERT INTO Person (PersonId) VALUES
(1),
(2),
(3),
(4)
INSERT INTO Action (ActionId, PersonId, ActionTime) VALUES
(1, 1, '2014-02-01'),
(2, 1, '2014-02-02'),
(3, 2, '2014-02-02'),
(4, 3, '2014-03-05')
Run Code Online (Sandbox Code Playgroud)
我想运行一个查询,显示每个人在每个月的 15 日之间执行的操作数。例如,我正在尝试以下操作:
SELECT
Person.PersonId,
COALESCE(GroupA_Actions_Made, 0) AS GroupA_Actions_Made,
COALESCE(GroupB_Actions_Made, 0) AS GroupB_Actions_Made
FROM
Person
RIGHT OUTER JOIN (
SELECT
PersonId,
COUNT(*) AS GroupA_Actions_Made
FROM
Action
WHERE
ActionTime BETWEEN '2014-01-15 00:00:00' AND '2014-02-14 23:59:59'
GROUP BY
PersonId
) GroupA ON GroupA.PersonId = Person.PersonId
RIGHT OUTER JOIN (
SELECT
PersonId,
COUNT(*) AS GroupB_Actions_Made
FROM
Action
WHERE
ActionTime BETWEEN '2014-02-15 00:00:00' AND '2014-03-14 23:59:59'
GROUP BY
PersonId
) GroupB ON GroupB.PersonId = Person.PersonId
Run Code Online (Sandbox Code Playgroud)
但是,我正在尝试的查询返回以下内容:
PersonId | GroupA_Actions_Made | GroupB_Actions_Made
(null) 0 1
Run Code Online (Sandbox Code Playgroud)
但我想
PersonId | GroupA_Actions_Made | GroupB_Actions_Made
1 2 0
2 1 0
3 0 1
Run Code Online (Sandbox Code Playgroud)
(我不希望结果为没有采取行动的人返回任何东西。)
如何获得所需格式的结果?
更新
除了我必须按如下方式包装它们之外,每个答案都有效:
SELECT
PersonId,
GroupA_Actions_Made,
GroupB_Actions_Made
FROM (
-- (answer)
) t
WHERE
GroupA_Actions_Made > 0
OR GroupB_Actions_Made > 0
Run Code Online (Sandbox Code Playgroud)
使用 SQL Server Profiler,接受的答案似乎在大型数据集上具有最快的查询时间。
这会给你你想要的结果,但我不确定它是否是最灵活的一段代码。
SELECT p.PersonId,
SUM(CASE
WHEN a.ActionTime >= '2014-01-15 00:00:00'
AND a.ActionTime < '2014-02-15 00:00:00'
THEN 1
ELSE 0
END) AS GroupA_Actions_Made,
SUM(CASE
WHEN a.ActionTime >= '2014-02-15 00:00:00'
AND a.ActionTime < '2014-03-15 00:00:00'
THEN 1
ELSE 0
END) AS GroupB_Actions_Made
FROM
Person p
JOIN
Action a on p.PersonId = a.PersonId
GROUP BY p.PersonId
Run Code Online (Sandbox Code Playgroud)