如何将多行数据按cid合并为单行,展示指定step的cr_time
实现行转列查询:将step对应的cr_time转为单独列展示
现有数据表(假设表名为your_table)的结构与数据如下:
| cid | step | cr_time |
|---|---|---|
| 120 | S02 | 08-JUL-24 08.35.19.000 AM |
| 120 | S03 | 08-JUL-24 01.35.19.000 PM |
| 120 | S04 | 09-JUL-24 02.35.19.000 PM |
| 121 | S02 | 09-JUL-24 09.35.19.000 AM |
| 121 | S03 | 09-JUL-24 02.35.19.000 PM |
| 122 | S02 | 10-JUL-24 10.35.19.000 AM |
| 122 | S03 | 10-JUL-24 03.35.19.000 PM |
需求为:每个cid仅返回一行,将step为'S02'和'S03'的cr_time分别作为单独列展示,预期结果如下:
| cid | S02_cr_time | S03_cr_time |
|---|---|---|
| 120 | 08-JUL-24 08.35.19.000 AM | 08-JUL-24 01.35.19.000 PM |
| 121 | 09-JUL-24 09.35.19.000 AM | 09-JUL-24 02.35.19.000 PM |
| 122 | 10-JUL-24 10.35.19.000 AM | 10-JUL-24 03.35.19.000 PM |
以下是两种可行的实现方案:
方法1:CASE WHEN + 聚合函数(通用所有SQL数据库)
该方法兼容性极强,几乎所有关系型数据库都支持。通过CASE语句筛选指定step的cr_time,再用聚合函数提取有效值:
SELECT cid, MAX(CASE WHEN step = 'S02' THEN cr_time END) AS S02_cr_time, MAX(CASE WHEN step = 'S03' THEN cr_time END) AS S03_cr_time FROM your_table WHERE step IN ('S02', 'S03') -- 可选,过滤无关step提升查询效率 GROUP BY cid ORDER BY cid;
逻辑说明:
CASE WHEN会仅保留当前cid下对应step的cr_time,其余行返回NULLMAX()函数会自动忽略NULL,取出每个cid对应的有效时间值GROUP BY cid确保每个cid仅输出一行
方法2:使用PIVOT函数(适用于支持该语法的数据库)
如果你的数据库支持PIVOT(如Oracle、SQL Server、PostgreSQL 11+),可以用更简洁的语法实现:
Oracle/SQL Server版本:
SELECT * FROM ( SELECT cid, step, cr_time FROM your_table WHERE step IN ('S02', 'S03') ) PIVOT ( MAX(cr_time) FOR step IN ('S02' AS S02_cr_time, 'S03' AS S03_cr_time) ) ORDER BY cid;
PostgreSQL版本:
PostgreSQL需要借助crosstab函数,需先启用tablefunc扩展:
-- 仅需执行一次,启用扩展 CREATE EXTENSION IF NOT EXISTS tablefunc; SELECT * FROM crosstab( 'SELECT cid, step, cr_time FROM your_table WHERE step IN (''S02'', ''S03'') ORDER BY cid, step', 'SELECT unnest(''{S02,S03}''::text[])' ) AS ct(cid int, S02_cr_time timestamp, S03_cr_time timestamp) ORDER BY cid;
内容的提问来源于stack exchange,提问作者H Varma
相关产品推荐
相关产品推荐

