Rating system : How to select the next item for which the user didn't vote yet
Question
I have 3 tables with the following columns :
* users : user_id
* votes : user_id, creation_id
* creations : creation_id, creation_points
Each user
can vote one time for each creation
. When a user vote, this happens :
- Table
votes
: Insert a new line withuser_id
andcreation_id
(so we can check if the user has already voted for this creation) - Table
creations
: Add +1 to rowcreation_points
for the concerned creation
But now, I want that when the user has successfully voted for a creation, it displays him the next creation for which he didn't vote yet. How can I achieve that ?
I tried this way :
- Select the next
creation_id
fromcreations
table (wherecreation_id
is bigger than the currentcreation_id
) - Check if the couple
creation_id
&user_id
already exists in thevotes
table. If it exists, retry from 1).
The problem with this method is that it needs a lot of queries if the user has already voted for the next creation. It also create an infinite loop if he has already voted for all the creations. Is there others alternatives ?
Solution
If I understand how you are handling it, you seem to be on the right track by storing votes
as a user_id
and creation_id
. To get the next available creation, use a LIMIT 1
query that excludes the already voted-for creations:
This method uses a NOT IN()
subquery:
SELECT
creations.*
FROM creations
WHERE creation_id NOT IN (
SELECT creation_id FROM votes WHERE user_id = <the user_id>
)
ORDER BY creation_id ASC
LIMIT 1
Similar thing using NOT EXISTS
instead:
SELECT
creations.*
FROM creations
WHERE NOT EXISTS (
SELECT creation_id
FROM votes
WHERE
user_id = <the user_id>
AND creations.creation_id = votes.creation_id
)
ORDER BY creation_id ASC
LIMIT 1
OTHER TIPS
you can make a join on votes table
if your current creation_id = 123456
your user id = 789
SELECT c.creation_id
FROM creations AS c
INNER JOIN votes AS v ON v.creation_id = c.creations_id
WHERE c.creation_id > 123456 AND v.user_id != 789
ORDER BY c.creation_id ASC
LIMIT 0,1