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
个过滤器,正如我所建议的那样。
想按年算,类型按月排序
这是我的 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
个过滤器,正如我所建议的那样。