多次计数(*)与左连接一次

Multiple count(*) with left join in one shot

我有 2 个这样的表:

Table 用户:

   +--------------------------+-----------------+------+-----+---------+----------------+
   | Field                    | Type            | Null | Key | Default | Extra          |
   +--------------------------+-----------------+------+-----+---------+----------------+
   | user_id                  | int(8) unsigned | NO   | PRI | NULL    | auto_increment |
   | user_email               | varchar(40)     | NO   | UNI |         |                |
   | user_login               | varchar(30)     | YES  |     | NULL    |                |
   | user_password            | varchar(40)     | YES  |     | NULL    |                |
   | user_firstname           | varchar(30)     | YES  |     | NULL    |                |
   | user_lastname            | varchar(50)     | YES  |     | NULL    |                |
   +--------------------------+-----------------+------+-----+---------+----------------+

Table users_oauth 至 link 具有 oauth 的用户,如果没有用户的 oauth 条目,则该用户已创建一个具有 email/password 的帐户:

   +----------------------+-----------------+------+-----+---------+----------------+
   | Field                | Type            | Null | Key | Default | Extra          |
   +----------------------+-----------------+------+-----+---------+----------------+
   | oauth_id             | int(8) unsigned | NO   | PRI | NULL    | auto_increment |
   | oauth_user_id        | int(8) unsigned | NO   | MUL | NULL    |                |
   | oauth_google_id      | varchar(30)     | YES  | UNI | NULL    |                |
   | oauth_facebook_id    | varchar(30)     | YES  | UNI | NULL    |                |
   | oauth_windowslive_id | varchar(30)     | YES  | UNI | NULL    |                |
   +----------------------+-----------------+------+-----+---------+----------------+

为了计算两个日期之间有多少新用户,我对 facebook oauth 执行了以下操作:

SELECT date_format(`user_date_accountcreated`, "%Y-%m-%d") AS  date, COUNT(*) AS total FROM users 
LEFT JOIN users_oauth ON users_oauth.oauth_user_id = users.user_id 
WHERE (user_date_accountcreated BETWEEN '2016-10-01 00:00:00' AND '2016-10-15 23:59:59') AND oauth_facebook_id IS NOT NULL
GROUP BY year(user_date_accountcreated), month(user_date_accountcreated), day(user_date_accountcreated)

和另一个使用 google oauth 的新用户请求,唯一的区别是 oauth_google_id IS NOT NULL 而不是 oauth_facebook_id IS NOT NULL:

SELECT date_format(`user_date_accountcreated`, "%Y-%m-%d") AS  date, COUNT(*) AS total FROM users 
LEFT JOIN users_oauth ON users_oauth.oauth_user_id = users.user_id 
WHERE (user_date_accountcreated BETWEEN '2016-10-01 00:00:00' AND '2016-10-15 23:59:59') AND oauth_google_id IS NOT NULL
GROUP BY year(user_date_accountcreated), month(user_date_accountcreated), day(user_date_accountcreated)

windows live oauth 的最后一个:

SELECT date_format(`user_date_accountcreated`, "%Y-%m-%d") AS  date, COUNT(*) AS total FROM users 
LEFT JOIN users_oauth ON users_oauth.oauth_user_id = users.user_id 
WHERE (user_date_accountcreated BETWEEN '2016-10-01 00:00:00' AND '2016-10-15 23:59:59') AND oauth_windowslive_id IS NOT NULL
GROUP BY year(user_date_accountcreated), month(user_date_accountcreated), day(user_date_accountcreated)

有什么方法可以将 3 个请求合并到一个 COUNT(*) AS total_facebookCOUNT(*) AS total_googleCOUNT(*) AS total_windowslive 中吗?

谢谢

您可以通过将 where 条件移动到 count 来实现。这称为条件聚合。

此外,当您left join 并使用 where 条件时,它会转换为内部联接。为避免将日期条件移至 left join.

SELECT 
date_format(`user_date_accountcreated`, "%Y-%m-%d") AS `date`, 
COUNT(case when oauth_facebook_id IS NOT NULL then 1 end ) AS total_facebook,
COUNT(case when oauth_google_id IS NOT NULL then 1 end) AS total_google,
COUNT(case when oauth_windowslive_id IS NOT NULL then 1 end) AS total_windowslive
FROM users 
LEFT JOIN users_oauth ON users_oauth.oauth_user_id = users.user_id 
AND user_date_accountcreated BETWEEN '2016-10-01 00:00:00' AND '2016-10-15 23:59:59'
GROUP BY date_format(`user_date_accountcreated`, "%Y-%m-%d")
--year(user_date_accountcreated), month(user_date_accountcreated), day(user_date_accountcreated)