[英]MySQL Pivoting Rows to Dynamic Columns
我们有一个表格,其中包括人员出入记录,如下所示:
人 | 天 | 时间 |
---|---|---|
1 | 2021 年 2 月 21 日 | 08:10 |
2 | 2021 年 2 月 21 日 | 08:11 |
1 | 2021 年 2 月 21 日 | 08:45 |
1 | 2021 年 2 月 21 日 | 09:18 |
1 | 2021 年 2 月 21 日 | 10:45 |
7 | 2021 年 2 月 21 日 | 10:53 |
2 | 2021 年 2 月 21 日 | 17:06 |
1 | 2021 年 2 月 21 日 | 17:23 |
7 | 2021 年 2 月 21 日 | 17:31 |
1 | 2021 年 2 月 22 日 | 08:13 |
5 | 2021 年 2 月 22 日 | 08:19 |
2 | 2021 年 2 月 22 日 | 08:20 |
2 | 2021 年 2 月 22 日 | 08:23 |
5 | 2021 年 2 月 22 日 | 09:47 |
5 | 2021 年 2 月 22 日 | 11:03 |
5 | 2021 年 2 月 22 日 | 18:06 |
5 | 2021 年 2 月 22 日 | 19:08 |
2 | 2021 年 2 月 22 日 | 19:01 |
5 | 2021 年 2 月 22 日 | 22:37 |
5 | 2021 年 2 月 23 日 | 08:15 |
1 | 2021 年 2 月 23 日 | 08:15 |
1 | 2021 年 2 月 23 日 | 14:30 |
5 | 2021 年 2 月 23 日 | 17:05 |
有了这些数据,我们想要 select 他们如下:
人 | 天 | 时间1 | 时间2 | 时间3 | 时间4 | 时间5 | 时间6 |
---|---|---|---|---|---|---|---|
1 | 2021 年 2 月 21 日 | 08:10 | 08:45 | 09:18 | 10:45 | 17:23 | |
2 | 2021 年 2 月 21 日 | 08:11 | 17:06 | ||||
7 | 2021 年 2 月 21 日 | 10:53 | 17:31 | ||||
1 | 2021 年 2 月 22 日 | 08:13 | |||||
2 | 2021 年 2 月 22 日 | 08:20 | 08:23 | 19:01 | |||
5 | 2021 年 2 月 22 日 | 08:19 | 09:47 | 11:03 | 18:06 | 19:08 | 22:37 |
1 | 2021 年 2 月 23 日 | 08:15 | 14:30 | ||||
5 | 2021 年 2 月 23 日 | 08:15 | 17:05 |
最简单的解决方案不是在 SQL 中执行此操作,而是通过简单的查询获取所有数据:
SELECT person, day, time FROM WeHaveATable ORDER BY day, person, time;
然后编写应用程序代码以根据需要在网格中呈现它。
在 SQL 中这很棘手的原因是 SQL 要求您在准备查询之前拼出选择列表中的所有列。 那是在它有机会读取数据以了解次数最多的人将有多少列之前。
SQL 中无法通过读取数据并根据在读取数据时发现的内容将更多列附加到选择列表来生成“动态列”。
所以在SQL中做一个pivot的方法是首先要知道有多少列。
SELECT MAX(c) FROM (SELECT COUNT(*) FROM WeHaveATable GROUP BY person) AS t;
然后使用 window function 形成一个查询,对每人/天的行数进行编号,并在数据透视表查询中使用该查询,每次使用一列,直到您在上一个查询中获得的最大次数。
WITH cte AS (
SELECT person, day, time, ROW_NUMBER() OVER (PARTITION BY day, person ORDER BY time) AS colno
FROM WeHaveATable;
)
SELECT day, person,
MAX(CASE colno WHEN 1 THEN time END) AS Time1,
MAX(CASE colno WHEN 2 THEN time END) AS Time2,
MAX(CASE colno WHEN 3 THEN time END) AS Time3,
MAX(CASE colno WHEN 4 THEN time END) AS Time4,
MAX(CASE colno WHEN 5 THEN time END) AS Time5,
MAX(CASE colno WHEN 6 THEN time END) AS Time6
FROM cte
GROUP BY day, person;
如果这看起来像是很多令人困惑的、细致的工作,那你是对的。 这就是为什么建议在 SQL 中跳过解决此问题的原因。 执行我在顶部显示的简单查询,然后编写应用程序代码以根据需要将结果处理到网格中。
有关列需求的数据驱动列表,请参阅http://mysql.rjweb.org/doc.php/pivot
它构建SELECT
并可选择运行它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.