使用自联接计数不正确

时间:2014-12-09 14:34:01

标签: sql sql-server

我试图在每个年级和每个调查年度的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

2 个答案:

答案 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

当我拍摄它时遇到问题时,我删除了该组,以便能够看到所有行。我应该看到四年级的调查属于三年级的空位,这让我想到了真正的原因。