Oracle中如何将垂直查询结果转换为水平格式?
问题描述
我通过多表连接的复杂查询得到了行式结构的结果,现在需要将其转换为指定的列式结构,而且不需要进行任何聚合操作。之前试过用PIVOT,但因为不需要聚合不知道怎么处理,请问该怎么实现这个需求?
解决方案
其实可以借助CASE WHEN配合分组来实现,或者用PIVOT搭配不改变结果的聚合函数(比如MAX/MIN)——因为当每个分组内对应目标列的记录唯一时,这类聚合函数只是提取唯一值,不会产生真正的聚合效果。
方法一:CASE WHEN + 分组
假设原查询结果包含主标识ID、属性名、属性值三个字段,要转成每个主标识ID一行,不同属性名作为列,示例SQL如下:
SELECT 主标识ID, -- 每个属性对应一列,用CASE WHEN匹配取值 MAX(CASE WHEN 属性名 = '姓名' THEN 属性值 END) AS 姓名, MAX(CASE WHEN 属性名 = '年龄' THEN 属性值 END) AS 年龄, MAX(CASE WHEN 属性名 = '部门' THEN 属性值 END) AS 部门 FROM ( -- 这里替换成你的多表连接复杂查询语句 SELECT 主标识ID, 属性名, 属性值 FROM ... ) AS 原查询结果 GROUP BY 主标识ID;
方法二:用PIVOT实现(以SQL Server为例)
如果你的数据库支持PIVOT,可以直接用它,指定MAX作为聚合函数即可——因为每个主标识ID+属性名的组合唯一,聚合后还是原数据:
SELECT 主标识ID, 姓名, 年龄, 部门 FROM ( -- 原多表连接查询 SELECT 主标识ID, 属性名, 属性值 FROM ... ) AS 源数据 PIVOT ( MAX(属性值) FOR 属性名 IN ([姓名], [年龄], [部门]) ) AS 透视结果;
方法三:FILTER子句(PostgreSQL等支持的数据库)
如果用PostgreSQL这类支持FILTER子句的数据库,写法更直观:
SELECT 主标识ID, MAX(属性值) FILTER (WHERE 属性名 = '姓名') AS 姓名, MAX(属性值) FILTER (WHERE 属性名 = '年龄') AS 年龄, MAX(属性值) FILTER (WHERE 属性名 = '部门') AS 部门 FROM ( -- 原多表连接查询 SELECT 主标识ID, 属性名, 属性值 FROM ... ) AS 原查询结果 GROUP BY 主标识ID;
内容的提问来源于stack exchange,提问作者Eddie
相关产品推荐
相关产品推荐

