基于InfoID实现行转列:SQL多条件查询合并求助
解决方法:行转列合并多查询结果
Hey there! 这是一个典型的**行转列(Pivot)**需求,核心是把同一个ObjID下不同InfoID对应的InfoVal值,转换成单独的列展示。下面给你两种通用的实现方案,适配大部分主流SQL数据库:
方法一:条件聚合(兼容性最强)
这种方法几乎支持所有SQL数据库(MySQL、SQL Server、PostgreSQL、Oracle等),思路是通过GROUP BY ObjID分组,再用CASE语句配合聚合函数(比如MAX)提取对应InfoID的值,邮箱部分因为可能有多个,用字符串聚合函数合并。
示例代码
SELECT ObjID, -- 提取报表名称(InfoID=1) MAX(CASE WHEN InfoID = 1 THEN InfoVal END) AS 报表名称, -- 提取存储过程名称(InfoID=4) MAX(CASE WHEN InfoID = 4 THEN InfoVal END) AS 存储过程名称, -- 合并所有关联邮箱(InfoID=16/17/23/24) -- 注意:不同数据库的字符串聚合函数语法不同,以下是常见版本: -- SQL Server/PostgreSQL: STRING_AGG(InfoVal, ', ') -- MySQL: GROUP_CONCAT(InfoVal SEPARATOR ', ') -- Oracle: LISTAGG(InfoVal, ', ') WITHIN GROUP (ORDER BY InfoID) STRING_AGG(CASE WHEN InfoID IN (16,17,23,24) THEN InfoVal END, ', ') AS 关联邮箱 FROM 主表 GROUP BY ObjID;
说明
- 用
MAX(CASE...)是因为每个ObjID对应InfoID=1和InfoID=4应该只有一条数据,MAX可以确保只取到那个唯一值(如果有重复也会取到非空的)。 - 邮箱部分如果有多个值,会用逗号分隔合并成一个字段;如果某个
ObjID没有对应邮箱,该字段会显示NULL。
方法二:使用PIVOT语法(部分数据库支持)
如果你的数据库支持PIVOT(比如SQL Server、Oracle),可以用更简洁的语法来处理报表名称和存储过程,邮箱部分还是需要配合字符串聚合:
示例代码(以SQL Server为例)
WITH PivotData AS ( SELECT ObjID, InfoID, InfoVal FROM 主表 WHERE InfoID IN (1,4) -- 先筛选需要转成列的InfoID ) SELECT p.ObjID, p.[1] AS 报表名称, p.[4] AS 存储过程名称, -- 单独查询合并邮箱 (SELECT STRING_AGG(InfoVal, ', ') FROM 主表 m WHERE m.ObjID = p.ObjID AND m.InfoID IN (16,17,23,24)) AS 关联邮箱 FROM PivotData PIVOT ( MAX(InfoVal) FOR InfoID IN ([1], [4]) ) AS p;
说明
- 先通过CTE筛选出需要转成列的
InfoID(1和4),再用PIVOT把行转成列。 - 邮箱部分通过子查询关联同一个
ObjID的邮箱数据,用STRING_AGG合并。
可视化示例参考
假设你的主表数据是这样的:
| ObjID | InfoID | InfoVal |
|---|---|---|
| 1 | 1 | 销售月报 |
| 1 | 4 | SP_GetSalesMonthly |
| 1 | 16 | sales@company.com |
| 1 | 23 | manager@company.com |
| 2 | 1 | 库存盘点表 |
| 2 | 4 | SP_GetStockCheck |
| 2 | 17 | warehouse@company.com |
运行方法一的SQL后,得到的结果会是:
| ObjID | 报表名称 | 存储过程名称 | 关联邮箱 |
|---|---|---|---|
| 1 | 销售月报 | SP_GetSalesMonthly | sales@company.com, manager@company.com |
| 2 | 库存盘点表 | SP_GetStockCheck | warehouse@company.com |
这样就把多个独立查询的结果合并成了一张包含所需列的单表啦!
内容的提问来源于stack exchange,提问作者Jona
相关产品推荐
相关产品推荐

