简体   繁体   中英

How to SELECT rows on a table with COUNT from other table in a range of time?

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 :

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 
             and f.time_created > UNIX_TIMESTAMP('2012-5-1 00:00:00') 
GROUP BY u.id, u.name, u.email ORDER BY num_fans DESC 

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 WHERE clause. 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 the user_fans table will not satisfy this condition (value will be NULL).

Having the condition in the on will join the users table only to the subset of the user_fans table - the outer join happens after this filtering.

Try adding is null to the condition:

SELECT u.id, u.name, u.email, COUNT(f.id) AS num_fans  
FROM users u  
LEFT OUTER JOIN user_fans f ON u.id=f.user_id  
WHERE f.time_created is null or f.time_created > UNIX_TIMESTAMP('2012-5-1 00:00:00')  
GROUP BY u.id, u.name, u.email  
ORDER BY num_fans DESC

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM