[英]MySQL Count and Convert Row to Colum Involve One Table Only
I have a table name histories that record user activities which consists of user_id, branch_id and duration.我有一个记录用户活动的表名历史记录,它由 user_id、branch_id 和持续时间组成。
The table look like this:该表如下所示:
+++++++++++++++++++++++++++++++++++
id | user_id | branch_id | totHours
+++++++++++++++++++++++++++++++++++
|1 | 100 | 1 | 1 |
|2 | 199 | 1 | 1 |
|3 | 121 | 1 | 1 |
|4 | 140 | 1 | 1 |
|5 | 103 | 2 | 3 |
|6 | 107 | 2 | 1 |
|7 | 299 | 1 | 2 |
|8 | 209 | 2 | 2 |
|9 | 119 | 1 | 5 |
I would like to produce an output like this:我想产生这样的输出:
+++++++++++++++++++++++++++
Hours | Branch A | Branch B
+++++++++++++++++++++++++++
|1 | 4 | 1 |
|2 | 1 | 1 |
|3 | 0 | 1 |
|4 | 0 | 0 |
|5 | 1 | 0 |
I try make it using this query, but when i use group by on totHours column only, it return error because i need to include the branch_id in the group by.我尝试使用此查询进行操作,但是当我仅在 totHours 列上使用 group by 时,它会返回错误,因为我需要在 group by 中包含 branch_id。
Here is my query:这是我的查询:
select totHours as Hours,
coalesce(case when branch_id = 1 then count(totHours) else 0 end) as 'Branch A',
coalesce(case when branch_id = 2 then count(totHours) else 0 end) as 'Branch B'
from histories
group by totHours, branch_id;
And if the totHours is not in the table (for example in this table 4), it will display 0 for both branch column.如果 totHours 不在表中(例如在此表 4 中),则两个分支列都将显示 0。
Here is my db fiddle这是我的数据库小提琴
Update: MySQL version 5.7.22更新:MySQL 版本 5.7.22
If you're using MySQL version 8+ (or any version support windows function), you can make use of the recursive common table expression to generate the hour values for you then LEFT JOIN
table histories
with it.如果您使用 MySQL 版本 8+(或任何版本支持 windows 功能),您可以使用递归公用表表达式为您生成小时值,然后使用它LEFT JOIN
表histories
。 After that you can do SUM()
with CASE
expression in SELECT
to generate your expected output:之后,您可以在SELECT
中使用CASE
表达式执行SUM()
以生成预期的输出:
WITH RECURSIVE hours AS (
SELECT 1 AS hr, MAX(totHours) AS maxth FROM histories UNION ALL
SELECT hr+1, maxth FROM hours WHERE hr+1 <= maxth)
SELECT hours.hr,
SUM(CASE WHEN histories.branch_id=1 THEN 1 ELSE 0 END) AS Branch_A,
SUM(CASE WHEN histories.branch_id=2 THEN 1 ELSE 0 END) AS Branch_B
FROM hours
LEFT JOIN histories
ON hours.hr=histories.totHours
GROUP BY hours.hr;
If you're using version that doesn't support window function, you can create a subquery to represent the hours (including missing hour).如果您使用的版本不支持窗口函数,您可以创建一个子查询来表示小时数(包括缺少的小时数)。 This is a hard-coding approach where you may have to always update the subquery to include new hour value (if any):这是一种硬编码方法,您可能必须始终更新子查询以包含新的小时值(如果有):
SELECT hours.hr,
SUM(CASE WHEN histories.branch_id=1 THEN 1 ELSE 0 END) AS Branch_A,
SUM(CASE WHEN histories.branch_id=2 THEN 1 ELSE 0 END) AS Branch_B
FROM
(SELECT 1 hr UNION
SELECT 2 UNION
SELECT 3 UNION
SELECT 4 UNION
SELECT 5) AS hours
LEFT JOIN histories
ON hours.hr=histories.totHours
GROUP BY hours.hr;
Edit the hours
subquery to add more, for example if you want until 7, you just add:编辑hours
子查询以添加更多内容,例如,如果您想要直到 7 点,您只需添加:
(SELECT 1 hr UNION
SELECT 2 UNION
SELECT 3 UNION
SELECT 4 UNION
SELECT 5 UNION
SELECT 6 UNION
SELECT 7) AS hours
to the subquery.到子查询。 Another way is to define the hours beforehand and create a reference table.另一种方法是预先定义小时数并创建参考表。 Let's say you estimate the hour to be until 100, then it's better if you create a table that stores 1-100 as reference for the LEFT JOIN
假设您估计小时为 100,那么最好创建一个存储 1-100 的表作为LEFT JOIN
的参考
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.