我试图在每个年级和每个调查年度的SurveyDatas表中计算每本书出现的次数。
在下面的查询中,BookId 300的Grade3列中的结果实际上应该是1,而不是它的116.对于Grade4列也是如此。如果我删除了Grade4 Count和JOIN,我得到58这是116的一半,但仍然不正确。我怀疑我需要使用子查询而不是左连接来处理我在这里尝试做的事情,或者甚至可能有更有效的方法来做这件事。 SQL Server公用表表达式会帮助我吗?我从未使用过该功能。
SELECT sd.SurveyYear, sd.BookId,
Count(sd3.Grade) as Grade3, Count(sd4.Grade) as Grade4
FROM SurveyDatas sd
LEFT JOIN SurveyDatas sd3 on sd3.BookId = sd.BookId
AND sd3.SurveyYear = sd.SurveyYear
AND sd3.Grade = '3'
LEFT JOIN SurveyDatas sd4 on sd4.BookId = sd.BookId
AND sd4.SurveyYear = sd.SurveyYear
AND sd4.Grade = '4'
GROUP BY sd.SurveyYear, sd.BookId
这是我的桌面结构和我的数据的样子,虽然我输入的数据比我在这里显示的数据还多。
SurveyDataId | SurveyYear | BookId | Grade
1 2014 300 3
2 2014 300 4
答案 0 :(得分:1)
你在两者之间获得了笛卡尔积。相反,只需使用条件聚合:
SELECT sd.SurveyYear, sd.BookId,
sum(case when sd.Grade = '3' then 1 else 0 end) as Grade3,
sum(case when sd.Grade = '4' then 1 else 0 end) as Grade4
FROM SurveyDatas sd
GROUP BY sd.SurveyYear, sd.BookId;
不需要自我加入。
答案 1 :(得分:0)
当您自行加入时,您需要考虑所有列。您没有使用SurverDataID,因为它没有全面了解。将其包含在您的加入条件中,您将看到您的期望。
SELECT sd.SurveyYear, sd.BookId,
Count(sd3.Grade) as Grade3, Count(sd4.Grade) as Grade4
FROM SurveyDatas sd
LEFT JOIN SurveyDatas sd3 on sd3.BookId = sd.BookId
AND sd3.SurveyYear = sd.SurveyYear
AND sd3.Grade = '3'
AND sd.SurveyDataID = sd3.SurveyDataID -- Add this line
LEFT JOIN SurveyDatas sd4 on sd4.BookId = sd.BookId
AND sd4.SurveyYear = sd.SurveyYear
AND sd4.Grade = '4'
AND sd.SurveyDataID = sd4.SurveyDataID -- And also this line
GROUP BY sd.SurveyYear, sd.BookId
当我拍摄它时遇到问题时,我删除了该组,以便能够看到所有行。我应该看到四年级的调查属于三年级的空位,这让我想到了真正的原因。