MySQL:以逗号分隔的项目数列表

时间:2017-07-01 12:50:17

标签: mysql sql

我有一个基于学生观看视频的学习系统,然后回答这些视频附带的问题。 (简化)模型基本上是这样的:

课程(课程定义,例如基础代数)

----------------------------------------
| id   | int     | auto_increment | PK |
| name | varchar |                |    |
----------------------------------------

课程实例(当用户开始课程时,此处会记录一个条目)

---------------------------------------------
| id        | int     | auto_increment | PK |
| course_id | int     |                | FK |
---------------------------------------------

视频(与特定课程相关)

---------------------------------------------
| id        | int     | auto_increment | PK |
| course_id | int     |                | FK |
| name      | varchar |                |    |
---------------------------------------------

问题(与给定视频相关)

--------------------------------------------
| id       | int     | auto_increment | PK |
| video_id | int     |                | FK |
| q_text   | varchar |                |    |
--------------------------------------------

我想要的是是获取所有课程实例和每个视频的问题数量,以逗号分隔。

例如,如果一门课程附有三个视频,第一个视频有两个问题,第二个和第三个视频各有一个问题,我想要这个:

-----------------------------------
| course_instance_id | qs_per_vid |
-----------------------------------
| 1                  | 3,2,2      |
-----------------------------------

我从自己的努力中得到的最好的就是:

SELECT
    ci.id,
    COUNT(DISTINCT videos.id) AS num_vids,
    GROUP_CONCAT(questions.video_id ORDER BY questions.video_id) AS questions
FROM course_instances ci
LEFT JOIN videos ON videos.course_id = ci.course_id
LEFT JOIN questions ON questions.video_id = videos.id
GROUP BY ci.id

产生类似的东西:

---------------------------------
| id | num_vids | questions     | <-- actually it's the vid ID of each question
---------------------------------
| 1  | 4        | 1,1,1,2,2,3,3 |
---------------------------------

...我可以通过重复的视频ID序列推断出第一个视频有三个问题,第二个和第三个有问题。

但我怎样才能最终得到我想要的输出?

1 个答案:

答案 0 :(得分:2)

你需要聚合两次。一种方法是在执行join

之前
SELECT ci.id,
       COUNT(v.id) AS num_vids,
       GROUP_CONCAT(q.numquestions ORDER BY q.video_id) AS questions
FROM course_instances ci LEFT JOIN
     videos v
     ON v.course_id = ci.course_id LEFT JOIN
     (SELECT q.video_id, COUNT(*) as numquestions
      FROM questions q
      GROUP BY q.video_id
     ) q
     ON q.video_id = v.id
GROUP BY ci.id;

子查询计算每个视频的问题数。然后外部查询将这些连接在一起成为您想要的结果字符串。