2014-09-25 93 views
2

我发现了一个类似的问题:What is the order of execution for this SQL statement。接受的答案指定FROM在任何其他子句之前执行。左连接两个表并计数时的SQL执行顺序

SELECT StudentName, Students.StudentID, Cnt 
FROM (
    SELECT Students.StudentID, count(StudentCourses.CourselD) as [Cnt] 
    FROM Students LEFT JOIN StudentCourses 
    ON Students.StudentID = StudentCourses.StudentID GROUP BY Students.StudentID 
) T INNER JOIN Students on T.StudentID = Students.StudentID 

count()在这种情况下如何工作?

我很困惑,因为它似乎不遵循我的逻辑。假设首先执行嵌套FROM中的LEFT JOIN(请让我知道这是否是错误的),我们将为每个学生至少有一行作为中间输出,如果学生没有参加任何课程,可能值为null 。如果将count()应用于该输出,则这样的学生将由于空值行而有1个计数,这在实际结果中不会发生。任何人都可以解释这个查询如何在引擎盖下执行吗?

在此先感谢

+0

你准确的问题是什么?该查询正常工作,因为有效。除此之外,您正在做出错误的假设:您不知道语句的执行顺序,因此您无法确定“FROM”语句总是先执行。 **逻辑顺序!=执行顺序** – Paolo 2014-09-25 13:33:56

+0

我看到查询是有效的,但我不知道如何应用count()。我已经在原始问题中做了一些澄清,如果您发现我的用词混乱,请告诉我。 – Jas 2014-09-25 13:56:34

回答

0

您的问题不是执行顺序。我认为这更多是由于以下事实:

COUNT(StudentCourses.CourselD) 

将只计算非空结果。

有了这个为:

SELECT Students.StudentID, count(*) as [Cnt] 
FROM Students LEFT JOIN StudentCourses 
ON Students.StudentID = StudentCourses.StudentID GROUP BY Students.StudentID 

将返回所有的计数,而不仅仅是那些课程ID是不为空。

+0

因此,经验法则是,使用count(*)来计算所有匹配的行,并计数(列)来计算那些列!= null? – Jas 2014-09-25 14:12:29

0

COUNT()在子查询中,而不是在外部查询中。您只能选择外部查询中由count()返回的值。

子查询中Cnt列的值将是一个大于或等于0的整数(因为COUNT(NULL)返回0,并非所有学生在StudentCourses表中都有行,我相信在该列中有零)。子查询为每个学生返回一行,其中COUNT()值为0或更多。

另外,由于Paolo在评论中提到 - 逻辑顺序!=执行顺序为,所以不要假设什么是在什么之前执行的。数据库引擎有多种机制来优化查询执行,因此您应该更喜欢阅读文档以假设某些工作是如何工作的。