按2列分组,包含2个连接,并返回包含总计的所有行

时间:2016-11-06 22:50:53

标签: mysql join group-by

我有3个表,我需要查询我需要按2列分组的地方,并且还要加入表格,但仍会返回所有结果。

Users
ID User_name Category Reason Change_date
1  John      1        2      2016-01-05
2  James     3        1      2015-10-02
3  Peter     1        4      2016-01-04
4  Tony      1        4      2016-01-15
5  Fred      1        4      2016-02-25
6  Rick      3        2      2016-04-19
7  Sonia     2        1      2016-10-14
8  Michelle  2        2      2015-11-09
9  Phillip   3        3      2016-03-01
10 Simon     3        3      2016-03-07

Category
ID Category_name
1  User
2  Super user
3  Admin

Reason
ID Reason_name
1  Promotion
2  Upgrade
3  Sponsor
4  Normal

我做了一些搜索并找到https://stackoverflow.com/a/28158276/1278201并修改了我的查询以尝试使用它:

SELECT category_name, reasons.reason_name, u1.id as user_id, user_name 
from users as u1
JOIN (SELECT id from users where users.change_date BETWEEN '2016-01-01' 
AND '2016-11-06' group by users.category, users.reason) AS u2
ON u1.id = u2.id
left join reason on u1.reason=category.id 
left join category on u1.category=category.id 

返回的结果仅使用group by - 我应该返回8行,但我只得到5,每个类别中每个原因的每次出现都是一行。

我的预期结果是:

category_name reason_name           user_id user_name
User          Upgrade               1       John
                                                                  "Upgrade" count       1
              Normal                3       Peter
                                    4       Tony
                                    5       Fred
                                                                  "Normal" count        3
                                                                  "User" count          4 
Super user    Promotion             7       Sonia
                                                                  "Promotion" count     1
                                                                  "Super user" count    1 
Admin         Upgrade               6       Rick
                                                                  "Upgrade" count       1
              Sponsor               9       Phillip
                                    10      Simon
                                                                  "Sponsor" count       2
                                                                  "Admin" count         3 

如何返回所有8行,并且能够获得每个category_namereason_name的计数?

2 个答案:

答案 0 :(得分:0)

您不应该在子查询中使用GROUP BY,因为它只会从每个组中返回一个用户ID。

事实上,你根本不需要子查询。您只需使用WHERE子句选择符合change_date条件的用户。

SELECT category_name, reasons.reason_name, u1.id as user_id, user_name 
from users as u1
left join reason on u1.reason=category.id 
left join category on u1.category=category.id 
where u1.change_date BETWEEN '2016-01-01' AND '2016-11-06'

要按类别和原因获取分组小计,可以使用GROUP BYWITH ROLLUP

SELECT category_name, reasons.reason_name, u1.id as user_id, user_name, COUNT(*) AS total
from users as u1
left join reason on u1.reason=category.id 
left join category on u1.category=category.id 
where u1.change_date BETWEEN '2016-01-01' AND '2016-11-06'
GROUP BY category_name, reason_name, user_id WITH ROLLUP

在显示结果的脚本中,总计位于user_idNULL的行中。类别总计也有reason IS NULL。因此,您可以在显示结果的脚本中正确显示这些行。如果你确实需要在MySQL中完成所有操作,可以将上述查询放在子查询中,包含的查询可以测试user_id IS NULLreason_name IS NULL

答案 1 :(得分:0)

对于您在预期输出中寻找的内容,这可能就是您要寻找的内容:

SELECT
Category_name, reason_name, users.ID,User_name
FROM
  Users 
  inner join Category on Category.ID=Users.Category
  inner join Reason on Reason.ID=Users.Reason
where users.change_date BETWEEN '2016-01-01' AND '2016-11-06'

SQLFiddle