SQL行转列实现:将时间区间按类别分列展示的查询需求
实现SQL方案
核心思路
- 用窗口函数
ROW_NUMBER()分别给class1、class2的时间区间按时间升序生成序号,序号相同的就是需要放在同一行的同序位区间 - 以生成的序号为关联条件,关联两类的区间数据,无匹配时自动补NULL
- 按序号排序保证结果顺序符合预期
完整SQL语句
假设你的表名为time_class,如果是其他表名自行替换即可:
WITH class1_rn AS ( SELECT `interval` AS class1, ROW_NUMBER() OVER (ORDER BY `interval` ASC) AS rn FROM time_class WHERE class = 'class1' ), class2_rn AS ( SELECT `interval` AS class2, ROW_NUMBER() OVER (ORDER BY `interval` ASC) AS rn FROM time_class WHERE class = 'class2' ) SELECT c1.class1, c2.class2 FROM class1_rn c1 FULL OUTER JOIN class2_rn c2 ON c1.rn = c2.rn ORDER BY COALESCE(c1.rn, c2.rn) ASC;
注:
interval是SQL保留关键字,所以用反引号包裹做转义,PostgreSQL、SQL Server等数据库可替换为双引号转义。MySQL不支持FULL OUTER JOIN,如果使用MySQL可直接替换为LEFT JOIN,适配你的样例场景下class1数量更多的情况。如果你的数据库不支持CTE语法(比如低于8.0版本的MySQL),可以把CTE部分改成子查询写法。
低版本MySQL适配方案
如果使用的MySQL版本低于8.0,不支持窗口函数,可以用变量手动生成序号:
SELECT c1.class1, c2.class2 FROM ( SELECT `interval` AS class1, @rn1 := @rn1 + 1 AS rn FROM time_class, (SELECT @rn1 := 0) init WHERE class = 'class1' ORDER BY `interval` ASC ) c1 LEFT JOIN ( SELECT `interval` AS class2, @rn2 := @rn2 + 1 AS rn FROM time_class, (SELECT @rn2 := 0) init WHERE class = 'class2' ORDER BY `interval` ASC ) c2 ON c1.rn = c2.rn ORDER BY c1.rn ASC;
内容的提问来源于stack exchange,提问作者Cornel Militaru
相关产品推荐
相关产品推荐

