左连接两个表并计数时的SQL执行顺序

时间:2014-09-25 10:31:35

标签: mysql sql sql-server

我发现了一个类似的问题:What is the order of execution for this SQL statement。接受的答案指定FROM在任何其他条款之前执行。

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,这在实际结果中不会发生。任何人都可以解释这个查询是如何在幕后执行的吗?

提前致谢

2 个答案:

答案 0 :(得分: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不为空的计数。

答案 1 :(得分:0)

COUNT()位于子查询中,外部查询中。您只能在外部查询中选择count()返回的值。

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

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