所以我正在研究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
当我只处理Answers表或Questions表时,一切正常。但是,一旦我尝试同时执行这两项操作(如上面的查询),COUNT就完全不起作用了。我得到的是COUNT(a.Id)与COUNT(q.Id)相同。所以我尝试减少查询以查看错误,并且我意识到我只需要在使用另一个表时将问题或答案表(甚至不在任何地方使用它们)添加到FROM子句中,并且一切都被破坏了。 / p>
我确信这是一件荒谬可笑的事情,我忽略了它,但它让我发疯,如果有人能指出我出了什么问题,我会感激不尽。提前谢谢。
答案 0 :(得分:5)
您未正确加入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
或者使用连接:
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
我不太了解SQL Server的查询优化器,所以我不能说哪一个会更快。第一个解决方案可以利用标量子查询缓存(如果在SQL Server中可用)。否则,第二个查询可能执行较少的嵌套循环。
答案 1 :(得分:3)
如其他地方所述,您在问题和答案上加入用户ID实际上会在两个表之间的用户级别生成一个笛卡尔联接。更好的方法是使用联合:
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
JOIN (select OwnerUserId,
Score q_score,
Id q_id,
NULL a_score,
NULL a_id
from Answers
union all
select OwnerUserId,
NULL q_score,
NULL q_id,
Score a_score,
Id a_id
from Questions) qa
ON qa.OwnerUserId = u.Id
GROUP BY u.Id, u.CreationDate
答案 2 :(得分:1)
不只是计算DISTINCT ID吗?
SELECT TOP 10
u.Id AS "UserId",
u.CreationDate AS "Member since",
AVG(q.Score) AS "Average Question Rating",
COUNT(DISTINCT q.Id) AS "N. of Questions posted by the agent",
AVG(a.Score) AS "Average Answer Rating",
COUNT(DISTINCT 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
答案 3 :(得分:-1)
如果是我,我会明确加入其他表格(答案和问题)。如果你不进行连接,它如何链接其他表?
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
would be
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
JOIN Answers a on u.ID = a.ID (assuming thats how answers and users are linked).
JOIN Questions q on a.ID = q.ID (assuming thats how questions and answers are linked)
WHERE q.OwnerUserId = u.Id
AND a.OwnerUserId = u.Id
GROUP BY u.Id, u.CreationDate