如何在具有多个 WHERE 条件的单个 SQL 查询中获取多个 COUNT?
How can I get multiple COUNT's in a single SQL query with multiple WHERE conditions?
我需要获取有关网络应用程序用户 activity 的报告。
首先,我有一个 table 来计算用户登录我们的应用程序的次数,如下所示:
user_activity
-----------------------------------------------------
| ID_login | Username | Date | Hour | ... |
|---------------------|------------|----------|-----|
| 1 | john | 2019-03-01 | 08:49:24 | ... |
| 2 | john | 2019-03-01 | 14:12:49 | ... |
| 3 | jane | 2019-03-03 | 10:02:31 | ... |
| ... | ... | ... | ... | ... |
-----------------------------------------------------
我想要做的是有一个报告,它不仅会给我一个设定时间段内每个用户的登录总量。我已经可以做到了。当我尝试获取上一年每个月的报告时,我遇到了困难,其中月份在不同的列中。
我希望我的查询生成的 table 看起来像这样:
user_activity
--------------------------------------------------------
| Username | login_total | login_jan | login_feb | ... |
|------------------------|-----------|-----------|-----|
| john | 4827 | 164 | 191 | ... |
| james | 3866 | 92 | 144 | ... |
| jane | 2979 | 104 | 92 | ... |
| ... | ... | ... | ... | ... |
--------------------------------------------------------
如您所见,我正在考虑使用 login_total 值来用于 ORDER BY。
这就是我现在所拥有的。
SELECT
user_activity.Username,
COUNT(user_activity.ID_login) AS login_total
FROM
user_activity
WHERE
user_activity.Date >= '2018-01-01'
AND
user_activity.Date <= '2018-12-31'
如何获得另一个包含 COUNT 个但具有不同条件的列?我应该把这些标准放在哪里?我试过使用 IF 语句和 HAVING 语句,但没有用。
我在想这样的事情...?
SELECT
user_activity.Username,
COUNT(
IF
(user_activity.Date >= '2019-01-01'
AND
user_activity.Date <= '2019-01-31')
user_activity.ID_login)
AS login_jan,
COUNT(
IF
(user_activity.Date >= '2019-02-01'
AND
user_activity.Date <= '2019-02-28')
user_activity.ID_login)
AS login_feb,
...
FROM
user_activity
似乎也没有用...我是否遗漏了什么?
我们可以做条件聚合,像这样:
SELECT ua.username
, SUM( ua.date >= '2019-01-01' AND ua.date < '2019-02-01' ) AS login_jan
, SUM( ua.date >= '2019-02-01' AND ua.date < '2019-03-01' ) AS login_feb
FROM user_activity ua
GROUP
BY ua.username
即使用MySQL shorthand,SUM()
聚合内的表达式将被计算为1、0或NULL。我们可以使用 MySQL IF() 函数或更便携的 ANSI SQL CASE 表达式
SELECT ua.username
, SUM(IF( ua.date >= '2019-01-01' AND ua.date < '2019-02-01' ,1,0)) AS login_jan
, SUM(IF( ua.date >= '2019-02-01' AND ua.date < '2019-03-01' ,1,0)) AS login_feb
FROM user_activity ua
GROUP
BY ua.username
或
SELECT ua.username
, SUM(CASE WHEN ua.date >= '2019-01-01' AND ua.date < '2019-02-01' THEN 1 ELSE 0 END) AS login_jan
, SUM(CASE WHEN ua.date >= '2019-02-01' AND ua.date < '2019-03-01' THEN 1 ELSE 0 END) AS login_feb
FROM user_activity ua
GROUP
BY ua.username
您正在尝试创建一个 PIVOT table,您可以使用条件聚合在 MySQL 中执行此操作。请注意,您可以使用 MONTH
and YEAR
函数简化表达式:
SELECT u.Username,
COUNT(*) AS login_total,
SUM(MONTH(u.Date) = 1) AS login_jan,
SUM(MONTH(u.Date) = 2) AS login_feb,
...
SUM(MONTH(u.Date) = 12) AS login_dec
FROM user_activity u
WHERE YEAR(u.Date) = 2018
GROUP BY u.Username
此查询还利用了以下事实:在数字上下文中 MySQL 将布尔表达式视为 1(真)或 0(假),从而允许我们 SUM
这些值。
我需要获取有关网络应用程序用户 activity 的报告。
首先,我有一个 table 来计算用户登录我们的应用程序的次数,如下所示:
user_activity
-----------------------------------------------------
| ID_login | Username | Date | Hour | ... |
|---------------------|------------|----------|-----|
| 1 | john | 2019-03-01 | 08:49:24 | ... |
| 2 | john | 2019-03-01 | 14:12:49 | ... |
| 3 | jane | 2019-03-03 | 10:02:31 | ... |
| ... | ... | ... | ... | ... |
-----------------------------------------------------
我想要做的是有一个报告,它不仅会给我一个设定时间段内每个用户的登录总量。我已经可以做到了。当我尝试获取上一年每个月的报告时,我遇到了困难,其中月份在不同的列中。
我希望我的查询生成的 table 看起来像这样:
user_activity
--------------------------------------------------------
| Username | login_total | login_jan | login_feb | ... |
|------------------------|-----------|-----------|-----|
| john | 4827 | 164 | 191 | ... |
| james | 3866 | 92 | 144 | ... |
| jane | 2979 | 104 | 92 | ... |
| ... | ... | ... | ... | ... |
--------------------------------------------------------
如您所见,我正在考虑使用 login_total 值来用于 ORDER BY。
这就是我现在所拥有的。
SELECT
user_activity.Username,
COUNT(user_activity.ID_login) AS login_total
FROM
user_activity
WHERE
user_activity.Date >= '2018-01-01'
AND
user_activity.Date <= '2018-12-31'
如何获得另一个包含 COUNT 个但具有不同条件的列?我应该把这些标准放在哪里?我试过使用 IF 语句和 HAVING 语句,但没有用。
我在想这样的事情...?
SELECT
user_activity.Username,
COUNT(
IF
(user_activity.Date >= '2019-01-01'
AND
user_activity.Date <= '2019-01-31')
user_activity.ID_login)
AS login_jan,
COUNT(
IF
(user_activity.Date >= '2019-02-01'
AND
user_activity.Date <= '2019-02-28')
user_activity.ID_login)
AS login_feb,
...
FROM
user_activity
似乎也没有用...我是否遗漏了什么?
我们可以做条件聚合,像这样:
SELECT ua.username
, SUM( ua.date >= '2019-01-01' AND ua.date < '2019-02-01' ) AS login_jan
, SUM( ua.date >= '2019-02-01' AND ua.date < '2019-03-01' ) AS login_feb
FROM user_activity ua
GROUP
BY ua.username
即使用MySQL shorthand,SUM()
聚合内的表达式将被计算为1、0或NULL。我们可以使用 MySQL IF() 函数或更便携的 ANSI SQL CASE 表达式
SELECT ua.username
, SUM(IF( ua.date >= '2019-01-01' AND ua.date < '2019-02-01' ,1,0)) AS login_jan
, SUM(IF( ua.date >= '2019-02-01' AND ua.date < '2019-03-01' ,1,0)) AS login_feb
FROM user_activity ua
GROUP
BY ua.username
或
SELECT ua.username
, SUM(CASE WHEN ua.date >= '2019-01-01' AND ua.date < '2019-02-01' THEN 1 ELSE 0 END) AS login_jan
, SUM(CASE WHEN ua.date >= '2019-02-01' AND ua.date < '2019-03-01' THEN 1 ELSE 0 END) AS login_feb
FROM user_activity ua
GROUP
BY ua.username
您正在尝试创建一个 PIVOT table,您可以使用条件聚合在 MySQL 中执行此操作。请注意,您可以使用 MONTH
and YEAR
函数简化表达式:
SELECT u.Username,
COUNT(*) AS login_total,
SUM(MONTH(u.Date) = 1) AS login_jan,
SUM(MONTH(u.Date) = 2) AS login_feb,
...
SUM(MONTH(u.Date) = 12) AS login_dec
FROM user_activity u
WHERE YEAR(u.Date) = 2018
GROUP BY u.Username
此查询还利用了以下事实:在数字上下文中 MySQL 将布尔表达式视为 1(真)或 0(假),从而允许我们 SUM
这些值。