Ishan Garg
Ishan Garg

Reputation: 318

MySQL : Selecting count of mutiple enum value

I am making a movie rating application where a user can rate a movie as either 'like' or 'dislike'. So I have made 3 tables user, movie and rating. The vote table's example is :

userID    movieID     Vote

 x        a           li
 y        a           dli
 y        b           li
 w        a           li

The table's schema is :

userID - PrimaryKey
movieID - PrimaryKey
Vote - Enum('li','dli')

I have made userID and movieID as primary key so that if the user updates his/her preference that specific row gets updated if the record is there.

Edit : Here's the movie table's schema.

mID - PrimaryKey
mName - Varchar
mGenre - Varchar
mDesc -  Text
mDateOfRelease - Date

My question is that is it possible to select all the columns from the movie table, and like and dislike count of that movie in one db call. If yes how can I do it?

Upvotes: 0

Views: 2725

Answers (3)

LKW
LKW

Reputation: 180

try this:

select m.*, 
sum(case when v.vote = li then 1 else 0 end) li_count, 
sum(case when v.vote = dli then 1 else 0 end) dli_count
from movie m left join vote v on m.movieID = v.movieID 
group by m.mId (which is enough in mySQL)

Upvotes: 1

Alexander B.
Alexander B.

Reputation: 636

Let' imagine that you have movie and it contains field id. Here is what you can do:

select m.*,sum(case when r.vote like 'li' then 1 else 0 end) likes,
sum(case when r.vote like 'dli' then 1 else 0 end) dislikes from movie m
left join rating r
on r.movieID = m.mID
group by m.mID;

Left join is basically for no-votes. If rating table will be empty for this movie - it will still show it.

Edit: To explain this I will cut this query.

We need to understand what group by is doing. You can find docs here. In short we create groups of the data based on the different entries of the column from your group by statement.

select count(r.movieID) from rating r
group by r.movieID;

This will give us how many votes each movie got (here we list only movies that got any vote - line in rating table). So after this we can do "smart" count, and use conditional SUM function. Into the definition you can have an expression. That means case when ... then ... end works as well. So we just sum up all the 'li' and do not touch 'dli' for likes and opposite for dislikes.

The only one big drawback of this is we don't have all the movies (think about the case when there is no votes for a movie). Then this select will just skip this. And here we have LEFT JOIN statement. The idea is very simple - we include all the lines of table movie no matter what is going on in rating table. on we use to connect these to tables. Then we recall what we did before with summing up but change group by to mID (it always exists and non-null, so we always have something to group on). In this case you will have exactly what you want. Also play around with this query (resulting one). Try to understand what will happen if you leave your rating column in group by statement. (It's easier to see than read tons of text :) )

If something is not clear - please let me know, will try to improve it.

Hope it helps

Upvotes: 2

Nisar P
Nisar P

Reputation: 316

Try this:

SELECT 
    votes.movieID, 
    likes.like_count, 
    dislikes.dislike_count
FROM votes
LEFT join (
    SELECT movieID, count(Vote) as like_count
    FROM votes
    WHERE Vote = 'li'
    GROUP BY movieID
) likes ON likes.movieID = votes.movieID
LEFT join (
    SELECT movieID, count(Vote) as dislike_count
    FROM votes
    WHERE Vote = 'dli'
    GROUP BY movieID
) likes ON likes.movieID = votes.movieID

Upvotes: 0

Related Questions