MySQL按GROUP BY结果过滤

时间:2014-09-12 03:25:48

标签: mysql sql

我不知道这是否可以通过子查询有效实现,或者如何为此构建查询。我必须提取一些关于不再使用我们系统的人的知识。想象一下,我们有3个用户ID为1024,1234和5678的用户;用户1024和1234正在使用主题A,而5678正在使用主题B:

$ SELECT * FROM user;  | $ SELECT * FROM user_theme;
+------+------+        | +------+-------+
|   id | name |        | | user | theme |
+------+------+        | +------+-------+
| 1024 | John |        | | 1024 |     A |
| 1234 | Jane |        | | 1234 |     A |
| 5678 | Jeff |        | | 5678 |     B |
+------+------+        | +------+-------+

使用情况跟踪表如下所示:

$ SELECT * FROM user_usage;
+----+------+---------------------+------+
| id | user | date                | uses |
+----+------+---------------------+------+
|  1 | 1234 | 2014-08-02 00:00:00 |    5 |
|  2 | 1234 | 2014-08-03 00:00:00 |    5 |
|  3 | 1234 | 2014-08-04 00:00:00 |    3 |
|  4 | 1234 | 2014-08-05 00:00:00 |    6 |
|  5 | 1024 | 2014-08-02 00:00:00 |    8 |
|  6 | 1024 | 2014-08-03 00:00:00 |    7 |
|  7 | 1024 | 2014-08-04 00:00:00 |    4 |
|  8 | 1024 | 2014-08-05 00:00:00 |    6 |
|  9 | 1024 | 2014-09-02 00:00:00 |    1 |
| 10 | 1024 | 2014-09-03 00:00:00 |    2 |
| 11 | 1024 | 2014-09-04 00:00:00 |    3 |
| 12 | 1024 | 2014-09-05 00:00:00 |    4 |
| 13 | 5678 | 2014-08-02 00:00:00 |    8 |
| 14 | 5678 | 2014-08-03 00:00:00 |    7 |
| 15 | 5678 | 2014-08-04 00:00:00 |    4 |
| 16 | 5678 | 2014-08-05 00:00:00 |    6 |
| 17 | 5678 | 2014-09-02 00:00:00 |    1 |
| 18 | 5678 | 2014-09-03 00:00:00 |    2 |
| 19 | 5678 | 2014-09-04 00:00:00 |    3 |
| 20 | 5678 | 2014-09-05 00:00:00 |    4 |
+----+------+---------------------+------+

我想了解分析情况,看看2014-09中我们的系统使用量有多少(又名:2014 - 08年有使用数据,但不再是2014-09),按主题分组。所以我想写一些类似的东西:

SELECT
    user_theme.theme,
    SUM(user_usage.users) 'uses lost'
FROM
    user_theme
    LEFT JOIN user_usage 
        ON user_theme.user = user_usage.user
WHERE
    ...
GROUP BY
    user_theme.theme
# HAVING ...?

得到如下结果:

+-------+-----------+
| theme | uses lost |
+-------+-----------+
|     A |        19 |
|     B |         0 |
+-------+-----------+

19来自SUM(uses) WHERE user = 1234 AND YEAR(date) = 2014 AND MONTH(date) = 8。 我事先并不知道我关心来自user = 1234的SUM(uses),因为我只知道我需要在SUM(uses)的WHERE子句中包含用户1234,因为{{ 1}} SUM(uses)为0。

实际上有很多用户,以及一些主题(大约20K用户,大约10个主题),所以理想情况下,我认为我想避免在代码中进行过滤直接在数据库中。有没有办法在MySQL中使用原始SQL查询有效地做到这一点?

1 个答案:

答案 0 :(得分:1)

以下是将当前月份与前一个月进行比较的查询:

set @current_month = now();
set @previous_month = date_sub(@current_month, interval 1 month);

set @current_month = concat(year(@current_month), month(@current_month));
set @previous_month = concat(year(@previous_month), month(@previous_month));

select a.`theme`, sum(ifnull(b.uses_lost,0)) as uses_lost
from
`user_theme` as a
left outer join
(
select `user`, sum(uses) as uses_lost
from `user_usage`
where concat(year(`date`), month(`date`)) = @previous_month
  and `user` not in (
    select `user`
    from `user_usage`
    where concat(year(`date`), month(`date`)) = @current_month)
group by `user`
) as b
on (a.`user`=b.`user`)
group by a.`theme`;

fiddle for play

主要想法是查找上个月使用过系统且当月没有行的所有用户