I have these tables:
users
-----
id INT
name VARCHAR(20)
email VARCHAR(40)
user_fans
----------
id INT
user_id INT /* linked to users.id */
fan_id INT /* linked to users.id */
time_created INT /* unix timestamp */
I can get all rows from table users with additional field named num_fans using the following query
SELECT u.id, u.name, u.email, COUNT(f.id) AS num_fans
FROM users u
LEFT JOIN user_fans f ON u.id=f.user_id
GROUP BY u.id, u.name, u.email
ORDER BY num_fans DESC
The problem is I need to get the num_fans in a range of time. I tried this query
SELECT u.id, u.name, u.email, COUNT(f.id) AS num_fans
FROM users u
LEFT JOIN user_fans f ON u.id=f.user_id
WHERE f.time_created > UNIX_TIMESTAMP('2012-5-1 00:00:00')
GROUP BY u.id, u.name, u.email
ORDER BY num_fans DESC
But the query above will return only users which already have fans. I want the rest of users also returned with num_fans=0.
Thanks for your help.
Move the condition to the
on:Update
(Added an explanation on @Gardon Dave’s suggestion)
The difference between what you have and this is:
In your query you have the condition in the
WHEREclause. This is applied after the Join,(see this as filtering on top of the join). If a row does not follow this condition it will be eliminated. Outer joined rows that do not have an entry in theuser_fanstable will not satisfy this condition (value will be NULL).Having the condition in the
onwill join the users table only to the subset of theuser_fanstable – the outer join happens after this filtering.