SQL练习疑问:为何需用JOIN关联表?COUNT函数选择有何依据?
SQL查询疑问:关联表必要性与COUNT函数选择
数据表结构与数据
TBL #1 - Fines(罚单表)
字段:fineID, fineDate, empID, amount
数据:
10001 2017-02-01 00:00:00.000 1 250.00 10002 2017-03-11 00:00:00.000 2 250.00 10003 2017-06-25 00:00:00.000 4 500.00 10004 2017-07-23 00:00:00.000 4 250.00 10005 2017-10-01 00:00:00.000 2 500.00 10006 2017-11-02 00:00:00.000 2 750.00 10007 2017-11-30 00:00:00.000 3 1000.00 10008 2017-12-03 00:00:00.000 1 250.00
TBL #2 - Complaints(投诉表)
字段:complaintId, compDate, fineId, description
数据:
1011 2017-08-01 00:00:00.000 10003 ##$&&! 1012 2017-07-30 00:00:00.000 10004 %$#&*&$#! 1013 2017-03-02 00:00:00.000 10001 $#^*&#! 1014 2017-11-10 00:00:00.000 10006 &$! 1015 2017-12-04 00:00:00.000 10007 *&%()#! 1016 2017-12-08 00:00:00.000 10007 8&(^$%$!
需求
检索收到最多投诉的罚单。
参考答案查询
SELECT TOP 1 f.fineId, COUNT(c.fineId) comp_count FROM fines f JOIN complaints c ON f.fineId = c.fineId GROUP BY f.fineId ORDER BY comp_count DESC;
自行编写的查询
SELECT TOP 1 fineId, COUNT(complaintId) comp_count FROM complaints GROUP BY fineId ORDER BY comp_count DESC;
疑问
作为SQL学习者,想了解:
- 为何参考答案必须使用JOIN关联Fines表?
- 使用
COUNT(fineId)而非COUNT(complaintId)是否必要?背后的设计逻辑是什么?
解答
1. 关于关联Fines表的必要性
从当前测试数据来看,你的查询完全正确,结果和参考答案一致,但参考答案关联Fines表主要是出于严谨性和扩展性考虑:
- 过滤脏数据:实际业务中可能存在投诉记录关联了不存在的罚单(比如罚单被删除,但投诉没清理),用
JOIN会自动过滤掉这些无效关联,确保统计的是真实存在的罚单的投诉数;而你的查询会把这些无效的fineId也统计进去,可能得到错误结果。 - 需求扩展性:如果后续需要展示罚单的额外信息(比如金额、日期),关联Fines表后可以直接在SELECT中添加字段,不需要重构查询结构。
- 当然,如果明确当前业务中Complaints的
fineId都是有效且关联Fines的,你的查询是更高效的简化写法。
2. 关于COUNT函数的选择
使用COUNT(c.fineId)还是COUNT(complaintId)不是必须的,两者在当前场景下结果一致,核心逻辑是:
COUNT()函数只统计非NULL值的数量。complaintId是投诉表的主键,必然非NULL;c.fineId是关联后的字段,只要关联有效也不会为NULL,所以两者统计的都是每个罚单对应的投诉记录数。- 甚至用
COUNT(*)会更稳妥,它直接统计分组后的行数,不需要依赖具体字段是否为NULL,结果完全相同。 - 参考答案用
COUNT(c.fineId)可能是个人习惯,或者想明确表达“统计关联到罚单的投诉数”,但不是强制要求。
内容的提问来源于stack exchange,提问作者Lana
相关产品推荐
相关产品推荐

