多次计数(*)与左连接一次
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_facebook
、COUNT(*) AS total_google
、COUNT(*) 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)
我有 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_facebook
、COUNT(*) AS total_google
、COUNT(*) 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)