如何通过嵌套SELECT查询结合LEFT JOIN生成性别得分统计表
没问题,我帮你把这些内容整理成规范的Markdown格式,并且给出合并查询的解决方案:
数据库表与查询合并方案
一、现有数据库表
1. student表
存储学生基础信息:
| student_id | name | gender |
|---|---|---|
| 1174 | Steve | male |
| 1175 | Jane | female |
| 1176 | Mark | male |
| 1177 | Lily | female |
2. period表
定义不同时间段的男女最大出勤人数限制:
| period_id | from | to | max_session_female | max_session_male |
|---|---|---|---|---|
| 1 | 2018-03-02 | 2018-03-04 | 14 | 15 |
| 2 | 2018-03-05 | 2018-03-08 | 20 | 20 |
3. attendance表
记录学生出勤打卡的详细信息:
| student_id | period_id | date | tapping_time | session |
|---|---|---|---|---|
| 1174 | 1 | 2018-03-02 | 15:30:49 | C |
| 1174 | 1 | 2018-03-02 | 19:56:15 | F |
| 1174 | 1 | 2018-03-03 | 05:10:20 | E |
| 1174 | 1 | 2018-03-03 | 12:28:54 | B |
| 1174 | 1 | 2018-03-03 | 15:31:12 | C |
| 1174 | 1 | 2018-03-04 | 12:26:33 | B |
| 1174 | 1 | 2018-03-04 | 15:39:06 | C |
| 1174 | 1 | 2018-03-04 | 18:32:40 | E |
| 1174 | 1 | 2018-03-04 | 19:56:09 | F |
| 1174 | 2 | 2018-03-05 | 05:14:55 | E |
| 1175 | 2 | 2018-03-05 | 12:27:29 | B |
| 1175 | 2 | 2018-03-05 | 19:53:19 | F |
| 1175 | 2 | 2018-03-06 | 12:25:45 | B |
| 1175 | 2 | 2018-03-08 | 12:29:41 | B |
| 1175 | 2 | 2018-03-08 | 15:32:14 | E |
| 1175 | 2 | 2018-03-08 | 20:24:03 | F |
| 1175 | 1 | 2018-03-02 | 05:15:13 | C |
| 1175 | 1 | 2018-03-02 | 12:36:19 | B |
| 1175 | 1 | 2018-03-02 | 15:38:20 | C |
| 1175 | 1 | 2018-03-02 | 19:52:09 | F |
| 1175 | 1 | 2018-03-03 | 05:14:24 | C |
| 1175 | 1 | 2018-03-03 | 12:29:26 | B |
| 1175 | 1 | 2018-03-03 | 15:31:48 | C |
| 1175 | 1 | 2018-03-03 | 19:55:41 | F |
| 1175 | 1 | 2018-03-04 | 12:29:52 | B |
| 1175 | 1 | 2018-03-04 | 15:40:39 | C |
| 1175 | 1 | 2018-03-04 | 19:53:18 | F |
| 1175 | 2 | 2018-03-05 | 05:12:05 | A |
| 1175 | 2 | 2018-03-05 | 12:29:27 | B |
| 1175 | 2 | 2018-03-05 | 15:28:16 | C |
| 1175 | 2 | 2018-03-05 | 19:55:52 | F |
| 1175 | 2 | 2018-03-06 | 05:15:10 | A |
| 1175 | 2 | 2018-03-06 | 12:32:10 | B |
| 1175 | 2 | 2018-03-06 | 15:33:11 | C |
| 1175 | 2 | 2018-03-06 | 20:13:48 | F |
| 1175 | 2 | 2018-03-07 | 05:13:25 | A |
| 1175 | 2 | 2018-03-07 | 12:28:13 | B |
| 1175 | 2 | 2018-03-07 | 15:37:28 | C |
| 1175 | 2 | 2018-03-07 | 20:23:06 | F |
| 1175 | 2 | 2018-03-08 | 05:11:47 | A |
| 1175 | 2 | 2018-03-08 | 12:31:43 | B |
| 1175 | 2 | 2018-03-08 | 15:28:29 | C |
| 1175 | 2 | 2018-03-08 | 20:21:29 | F |
| 1176 | 2 | 2018-03-07 | 20:50:43 | F |
| 1176 | 2 | 2018-03-08 | 19:54:32 | F |
| 1177 | 1 | 2018-03-02 | 05:13:30 | A |
| 1177 | 1 | 2018-03-02 | 12:38:29 | B |
| 1177 | 1 | 2018-03-02 | 19:53:38 | F |
| 1177 | 1 | 2018-03-03 | 05:12:33 | A |
| 1177 | 1 | 2018-03-03 | 12:34:48 | B |
| 1177 | 1 | 2018-03-03 | 15:39:05 | C |
| 1177 | 1 | 2018-03-03 | 20:00:51 | F |
| 1177 | 1 | 2018-03-04 | 05:10:59 | A |
| 1177 | 1 | 2018-03-04 | 12:33:56 | B |
| 1177 | 1 | 2018-03-04 | 15:39:09 | C |
| 1177 | 1 | 2018-03-04 | 19:48:59 | F |
| 1177 | 2 | 2018-03-05 | 05:12:15 | A |
| 1177 | 2 | 2018-03-05 | 12:30:53 | B |
| 1177 | 2 | 2018-03-05 | 15:34:53 | C |
| 1177 | 2 | 2018-03-05 | 19:53:19 | F |
| 1177 | 2 | 2018-03-06 | 05:12:56 | A |
| 1177 | 2 | 2018-03-06 | 12:30:03 | B |
| 1177 | 2 | 2018-03-06 | 15:31:00 | C |
| 1177 | 2 | 2018-03-06 | 19:52:40 | F |
| 1177 | 2 | 2018-03-07 | 05:12:30 | A |
| 1177 | 2 | 2018-03-07 | 12:34:48 | B |
| 1177 | 2 | 2018-03-07 | 15:40:34 | C |
| 1177 | 2 | 2018-03-07 | 19:53:47 | F |
| 1177 | 2 | 2018-03-08 | 05:11:21 | A |
| 1177 | 2 | 2018-03-08 | 12:35:21 | B |
| 1177 | 2 | 2018-03-08 | 15:36:26 | C |
| 1177 | 2 | 2018-03-08 | 19:52:32 | F |
二、现有男女得分查询
女性得分查询
SELECT (COUNT(a.tapping_time)/2)/p.max_session_female*100 AS 'women_score' FROM period p LEFT JOIN attendance a ON p.period_id = a.period_id LEFT JOIN student s ON a.student_id = s.student_id -- 修正原查询笔误:原语句中关联条件错误 WHERE s.gender = 'female' GROUP BY p.period_id
男性得分查询
SELECT (COUNT(a.tapping_time)/2)/p.max_session_male*100 AS 'men_score' FROM period p LEFT JOIN attendance a ON p.period_id = a.period_id LEFT JOIN student s ON a.student_id = s.student_id -- 修正原查询笔误:原语句中关联条件错误 WHERE s.gender = 'male' GROUP BY p.period_id
注:原查询存在关联条件笔误,
a.student_id = a.student_id应改为a.student_id = s.student_id,否则无法正确关联学生表获取性别信息。
三、合并查询生成统一统计表
要生成包含时间段信息、总出勤数、男女得分的统一报表,我们可以将男女得分查询作为子查询,与period表左连接,同时计算每个时间段的总出勤数:
SELECT p.period_id, p.`from`, p.`to`, COALESCE(total.total_att, 0) AS total_att, COALESCE(w.women_score, 0) AS women_score, COALESCE(m.men_score, 0) AS men_score FROM period p LEFT JOIN ( SELECT period_id, COUNT(tapping_time) AS total_att FROM attendance GROUP BY period_id ) total ON p.period_id = total.period_id LEFT JOIN ( SELECT p.period_id, ROUND((COUNT(a.tapping_time)/2)/p.max_session_female*100) AS women_score FROM period p LEFT JOIN attendance a ON p.period_id = a.period_id LEFT JOIN student s ON a.student_id = s.student_id WHERE s.gender = 'female' GROUP BY p.period_id ) w ON p.period_id = w.period_id LEFT JOIN ( SELECT p.period_id, ROUND((COUNT(a.tapping_time)/2)/p.max_session_male*100) AS men_score FROM period p LEFT JOIN attendance a ON p.period_id = a.period_id LEFT JOIN student s ON a.student_id = s.student_id WHERE s.gender = 'male' GROUP BY p.period_id ) m ON p.period_id = m.period_id ORDER BY p.period_id;
关键说明:
- 用
COALESCE函数处理空值,确保无出勤记录的时间段也显示0而非NULL; - 用
ROUND函数将得分取整,匹配期望结果的整数格式; - 新增总出勤数子查询,统计每个时间段的打卡总次数。
最终期望结果:
| period_id | from | to | total_att | women_score | men_score |
|---|---|---|---|---|---|
| 1 | 2018-03-02 | 2018-03-04 | 31 | 78 | 53 |
| 2 | 2018-03-05 | 2018-03-08 | 51 | 90 | 10 |
内容的提问来源于stack exchange,提问作者codefighter
相关产品推荐
相关产品推荐

