Reputation: 34556
I have a learning system based on students watching videos then answering questions attached to those videos. The (simplified) model is basically this:
Courses (a course definition, e.g. Basic Algebra)
----------------------------------------
| id | int | auto_increment | PK |
| name | varchar | | |
----------------------------------------
Course instances (an entry is logged in here when a user begins a course)
---------------------------------------------
| id | int | auto_increment | PK |
| course_id | int | | FK |
---------------------------------------------
Videos (associated with a given course)
---------------------------------------------
| id | int | auto_increment | PK |
| course_id | int | | FK |
| name | varchar | | |
---------------------------------------------
Questions (associated with a given video)
--------------------------------------------
| id | int | auto_increment | PK |
| video_id | int | | FK |
| q_text | varchar | | |
--------------------------------------------
What I want is to get all course instances and the number of questions per video, comma separated.
So for example, if a course had three videos attached to it, and the first video had two questions and the second and third video had one question each, I want this:
-----------------------------------
| course_instance_id | qs_per_vid |
-----------------------------------
| 1 | 3,2,2 |
-----------------------------------
The best I've got from my own efforts is this:
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
That produces something like:
---------------------------------
| id | num_vids | questions | <-- actually it's the vid ID of each question
---------------------------------
| 1 | 4 | 1,1,1,2,2,3,3 |
---------------------------------
...from which I can infer, by the repeated video ID sequences, that the first vid has three questions, and the second and third two.
But how can I end up with my desired output above?
Upvotes: 0
Views: 50
Reputation: 1269823
You need to aggregate twice. One method is before doing the 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;
The subquery counts the number of questions for each video. The outer query then concatenates these together into the result string that you want.
Upvotes: 2