GROUP BY 和 LEFT JOIN with COUNT from same table

GROUP BY and LEFT JOIN with COUNT from same table

想按年算,类型按月排序

这是我的 user table:

id  type  uname      date_created
1    fac   a      2015-12-28 17:11:19
2    cs    b      2015-12-23 19:09:51
3    cs    c      2015-12-23 19:09:21
4    stu   d      2015-12-31 18:12:41
5    fac   e      2015-11-11 00:00:00
6    fac   f      2015-10-07 00:00:00

预期结果:

fac  stu  cs
 1    1    2 // month january
 1    0    0 // month octomber
 1    0    0 // month november

我试过的是:

SELECT count(u1.id) as fac, count(u2.id) as stu, count(u3.id) as cs
FROM user u
left join user u1 ON u1.faculty = 'yes' AND YEAR(u1.date_created) = 2015
left join user u2 ON u2.faculty = 'no' AND YEAR(u2.date_created) = 2015
left join user u3 ON u3.faculty = 'club_student' AND YEAR(u3.date_created) = 2015
GROUP BY MONTH(u.date_created) ORDER BY MONTH(u.date_created)

给我错误的结果,例如:

fac  stu  cs
6    6    6 
6    6    6 
24   24   24

尝试 count(distinct):

SELECT count(distinct u1.id) as fac, count(distinct u2.id) as stu,
       count(distinct u3.id) as cs
FROM user u left join
     user u1
     ON u1.faculty = 'yes' AND YEAR(u1.date_created) = 2015 left join
     user u2
     ON u2.faculty = 'no' AND YEAR(u2.date_created) = 2015 left join
     user u3
     ON u3.faculty = 'club_student' AND YEAR(u3.date_created) = 2015
GROUP BY MONTH(u.date_created) ORDER BY MONTH(u.date_created)

您需要的是 PIVOT 命令将行转列。实际上,MySQL不支持这种操作,所以我们需要手动使用CASE WHEN(见SQLFiddle):

select 
  month(date_created) as month,
  count(case when faculty = 'yes' THEN 1 END) as fac,
  count(case when faculty = 'no'  THEN 1 END) as stu,
  count(case when faculty = 'club_student' THEN 1 END) as cs
from user
where 1=1
  and date_created >= STR_TO_DATE('01-01-2015','%d-%m-%Y')
  and date_created <  STR_TO_DATE('01-01-2016','%d-%m-%Y')
group by month(date_created)
order by month(date_created)

实际上,您的连接语法没有意义...您需要连接 3 次以计算每个 tables 中的 id...从左连接开始,数据来自这些 tables 将在有连接匹配时返回,在没有匹配的情况下返回 null ... null 值不计入 COUNT 聚合函数,因此您的连接语法可以简化为INNER 加入语法。但是您甚至不需要 INNER 加入,因为您加入的是相同的 table,而且您实际上没有将 FROM table 中的任何列与 JOIN tables.

这样,您定义的过滤器可以减少为 WHERE 个过滤器和 CASE WHEN 个过滤器,正如我所建议的那样。