如何实现带JOIN的COUNT与GROUP BY查询?SQL语句求助
解决数据库分组统计关联查询的问题
嘿,我来帮你搞定这个统计查询的问题!你原来的SQL语句有几个语法和逻辑上的问题,我先帮你梳理清楚,然后给出正确的写法。
问题分析
你的核心需求是:
- 按
kelas表的id_kelas分组 - 统计每个班级对应的
daftar表中唯一报名记录数(保留你要求的DISTINCT id_daftar逻辑) - 同时关联
matkul和proker表获取课程、项目的相关信息 - 最终按
nama_matkul排序
原来的SQL存在这些问题:
- 子查询语法错误:你在SELECT子句里直接写了
SELECT COUNT(DISTINCT daftar.id_daftar) group by daftar.id_kelas,这不符合子查询的语法规范,而且这种写法会返回多个结果,无法直接作为单个字段的值。 - 未关联
daftar表:主查询里根本没和daftar表做JOIN,自然无法统计该表的数据。 SELECT *在分组查询中不合适:分组查询时,SELECT里的非聚合字段需要包含在GROUP BY中(或符合数据库的分组规则),直接用SELECT *会导致语法错误。
正确的SQL写法(两种方案)
方案一:JOIN后直接分组统计(逻辑直观)
这种写法适合数据量中等的场景,逻辑清晰易懂:
SELECT kelas.id_kelas, kelas.nama_kelas, kelas.kapasitas, matkul.nama_matkul, proker.nama_proker, COUNT(DISTINCT daftar.id_daftar) AS total_pendaftar FROM kelas INNER JOIN matkul ON kelas.id_matkul = matkul.id_matkul INNER JOIN proker ON kelas.id_proker = proker.id_proker -- 用LEFT JOIN确保即使没有报名的班级也能显示,统计数为0 LEFT JOIN daftar ON kelas.id_kelas = daftar.id_kelas -- 分组字段要包含所有SELECT中的非聚合字段,符合数据库分组规范 GROUP BY kelas.id_kelas, kelas.nama_kelas, kelas.kapasitas, matkul.nama_matkul, proker.nama_proker ORDER BY matkul.nama_matkul;
方案二:先统计子查询再关联(性能更优)
如果daftar表数据量很大,先单独统计每个班级的报名数,再关联其他表会减少关联计算量,性能更好:
SELECT kelas.*, matkul.nama_matkul, proker.nama_proker, -- 用COALESCE处理NULL,把没有报名的班级统计数设为0 COALESCE(daftar_stats.total_pendaftar, 0) AS total_pendaftar FROM kelas INNER JOIN matkul ON kelas.id_matkul = matkul.id_matkul INNER JOIN proker ON kelas.id_proker = proker.id_proker LEFT JOIN ( -- 子查询先完成每个班级的唯一报名数统计 SELECT id_kelas, COUNT(DISTINCT id_daftar) AS total_pendaftar FROM daftar GROUP BY id_kelas ) AS daftar_stats ON kelas.id_kelas = daftar_stats.id_kelas ORDER BY matkul.nama_matkul;
结果说明
根据你提供的测试数据,执行上述SQL后会得到符合预期的结果:
| id_kelas | nama_kelas | kapasitas | nama_matkul | nama_proker | total_pendaftar |
|---|---|---|---|---|---|
| 0 | nini | 3 | akuntansi biayaz | Mentoring Accounting Club | 4 |
| 7 | Aduh | 1 | akuntansi biayaz | Bebelac | 1 |
| 6 | B | 30 | ewean | Mentoring Accounting Club | 1 |
内容的提问来源于stack exchange,提问作者Aufa Murtafi Rifqi




