所以我正在研究SQL Server 2008,我有这个查询应该很简单,但由于某种原因不起作用.它看起来基本上是这样的:
SELECT TOP 10
u.Id AS "UserId",
u.CreationDate AS "Member since",
AVG(q.Score) AS "Average Question Rating",
COUNT(q.Id) AS "N. of Questions posted by the agent",
AVG(a.Score) AS "Average Answer Rating",
COUNT(a.Id) AS "N. of Answers posted by the agent"
FROM
Users u,
Answers a,
Questions q
WHERE q.OwnerUserId = u.Id
AND a.OwnerUserId = u.Id
GROUP BY u.Id, u.CreationDate
Run Code Online (Sandbox Code Playgroud)
当我只在Answers表或Questions表上工作时,一切正常.但是,一旦我尝试同时执行这两项操作(如上面的查询),COUNT就完全不起作用了.我得到的是COUNT(a.Id)与COUNT(q.Id)相同.所以我尝试减少查询以查看错误,并且我意识到我只需要在使用其他表时将问题或答案表(即使不使用它们)添加到FROM子句中,一切都被破坏了.
我确定这是一件非常微不足道的事情,我忽略了它但它让我发疯了,如果有人能指出我出了什么问题,我会感激不尽.先感谢您.
您没有加入Answers并Questions正确地进行聚合.在Answers和之间Questions,结果是笛卡尔积(对于每个用户,每个答案都与每个问题相结合)
解决此问题的最简单方法是在子查询中执行聚合:
SELECT TOP 10
u.Id AS "UserId",
u.CreationDate AS "Member since",
ISNULL((SELECT AVG(Score) FROM Answers WHERE OwnerUserId = u.Id), 0)
AS "Average Question Rating",
(SELECT COUNT(*) FROM Answers WHERE OwnerUserId = u.Id)
AS "N. of Questions posted by the agent",
ISNULL((SELECT AVG(Score) FROM Questions WHERE OwnerUserId = u.Id), 0)
AS "Average Answer Rating",
(SELECT COUNT(*) FROM Questions WHERE OwnerUserId = u.Id)
AS "N. of Answers posted by the agent"
FROM Users u
Run Code Online (Sandbox Code Playgroud)
或者使用连接:
SELECT TOP 10
u.Id AS "UserId",
u.CreationDate AS "Member since",
ISNULL(q.a, 0) AS "Average Question Rating",
ISNULL(q.c, 0) AS "N. of Questions posted by the agent",
ISNULL(a.a, 0) AS "Average Answer Rating",
ISNULL(a.c, 0) AS "N. of Answers posted by the agent"
FROM Users u
-- If you LEFT JOIN these tables, you'll get also results for users without
-- questions or answers
LEFT OUTER JOIN (SELECT OwnerUserId, AVG(Score) a, COUNT(*) c
FROM Questions GROUP BY OwnerUserId) q
ON q.OwnerUserId = u.Id
LEFT OUTER JOIN (SELECT OwnerUserId, AVG(Score) a, COUNT(*) c
FROM Answers GROUP BY OwnerUserId) a
ON a.OwnerUserId = u.Id
Run Code Online (Sandbox Code Playgroud)
我不太了解SQL Server的查询优化器,所以我不能说哪一个会更快.第一个解决方案可以利用标量子查询缓存(如果在SQL Server中可用).否则,第二个查询可能执行较少的嵌套循环.