I’m struggling with a task that could be very simple but I’m having a hard time figuring it out. I’ve two database table:
options_table
option_id | option_name | question_id |
1 | opt one | 4 |
2 | opt two | 4 |
3 | opt three | 4 |
4 | opt four | 4 |
and votes_table
question_id | survey_id | option_id |
4 | 1 | 1 |
4 | 1 | 2 |
4 | 1 | 2 |
4 | 1 | 1 |
4 | 1 | 3 |
4 | 1 | 2 |
From this example, we have 2 votes on option 1, 3 votes on option 2 and 1 vote on option 3, but none on option 4.
I’d like to retrieve all the options name with the relative count, but I can’t get the option without votes. I’m sure I’m overlooking something, it’s workday’s end and I must be tired.
I tried something like:
SELECT o.option_name, count(*) as cnt
FROM votes_table AS v
JOIN options_table AS o
ON o.option_id = v.option_id
WHERE v.survey_id = 1
GROUP BY o.option_name
but I just get
option_name | option_id | cnt
opt one | 1 | 2
opt two | 2 | 3
opt three | 3 | 1
How do I get also “opt four”? So I can properly display all the survey results including the option noone voted. I also tried using OUTER JOINs, but to no avail.
I’m ashamed for this might sound a stupid question, but I still have a lot to learn on databases and relationships
Use
LEFTinstead ofINNERjoin – put in the Left side the table with all the options, and in the Right side the table with missing options.Move any condition that uses a column from the Right table, like the
v.survey_id = 1one, from theWHEREto theONclause.Use
COUNT(RightTable.column)instead ofCOUNT(*), so you get0for options not voted:I suppose that
(option_id, question_id)is the Primary (or a Unique) Key of theoptionstable. That’s why you either need toGROUP BYboth of them orWHERE o.question_idandGROUP BY o.option_id.Otherwise, if you only
GROUP BY o.option_id, the query for every option, will count votes for all questions that were voted with this option.