SQL技术问询:统计学生11月Offer数时WHERE与COUNT(*)的问题
问题:查询学生11月Offer数量的SQL疑问
需求与表结构
需要编写SQL查询每个学生在11月获得的Offer数量,输出列名为Job_Offers,结果按学生Id排序。
表结构如下:
-- Students表(学生信息) Id: INT (主键) Name: VARCHAR -- Jobs表(Offer信息) Id: INT(关联Students表的Id,标识该Offer属于哪个学生) Date: DATE(Offer发放日期) Salary: INT(薪资)
错误代码与正确代码
错误代码(输出结果不符合预期)
SELECT COUNT(Jobs.Id) AS Job_Offers FROM Students LEFT JOIN Jobs ON Students.Id = Jobs.Id WHERE MONTH(Jobs.Date) = 11 GROUP BY Students.Id ORDER BY Students.Id
正确代码
SELECT COUNT(Jobs.Id) AS Job_Offers FROM Students LEFT JOIN Jobs ON Students.Id = Jobs.Id AND MONTH(Jobs.Date) = 11 GROUP BY Students.Id ORDER BY Students.Id
疑问解答
1. 为什么不能用WHERE子句?
LEFT JOIN的核心作用是保留左表(Students)的所有记录,哪怕右表(Jobs)没有匹配的数据(此时Jobs的字段会是NULL)。
如果把MONTH(Jobs.Date) = 11放在WHERE子句里,会对LEFT JOIN后的完整结果集做过滤:
- 对于11月没有拿到Offer的学生,Jobs.Date是NULL,
MONTH(NULL)的结果也是NULL,NULL = 11不成立,这类学生的记录会被直接过滤掉,最终结果里就看不到他们的Job_Offers=0的记录,完全不符合“每个学生都要统计”的需求。
而把条件放在JOIN的ON子句里,是在表关联阶段就只筛选11月的Jobs记录,没有匹配到的学生依然会被保留,对应的Jobs字段为NULL,后续统计时就能得到正确的0值。
2. 为什么COUNT(*)无法正常工作?
COUNT(*)会统计所有非空的行,包括LEFT JOIN后生成的“学生无匹配Offer”的记录——因为这些行里Students的字段都是有效值,COUNT(*)会把这行算成1,而不是正确的0。
而COUNT(Jobs.Id)只会统计Jobs.Id不为NULL的行数:只有当学生有11月的Offer时,Jobs.Id才会有值,否则是NULL不会被统计,这样就能得到准确的Offer数量,包括无Offer时的0。
内容的提问来源于stack exchange,提问作者Abhishek Verma
相关产品推荐
相关产品推荐

