将行值转换为列名
Posted
技术标签:
【中文标题】将行值转换为列名【英文标题】:Transform Row Values to Column Names 【发布时间】:2020-10-07 15:57:47 【问题描述】:我有一张客户联系人及其角色的表格。下面的简化示例。
customer | role | userid
----------------------------
1 | Support | 123
1 | Support | 456
1 | Procurement | 567
...
想要的输出
customer | Support1 | Support2 | Support3 | Support4 | Procurement1 | Procurement2
-----------------------------------------------------------------------------------
1 | 123 | 456 | null | null | 567 | null
2 | 123 | 456 | 12333 | 45776 | 888 | 56723
因此,根据该角色的用户数量动态创建所需列的数量。这是少数角色。我也可以假设最多 5 个用户担任同一角色。这意味着最坏的情况我需要为每个角色生成 5 列。用户 ID 无需按任何特定顺序排列。
我目前的方法是为每个角色/客户获取 1 个用户 ID。然后第二个查询提取另一个不属于第一个结果集的 id。等等。但这样我必须静态创建 5 个查询。有用。但我想知道是否有更有效的方法?动态创建所需的列。
每个角色拉一个用户的示例:
SELECT customer,role,
(SELECT top 1 userid
FROM temp as tmp1
where tmp1.customer=tmp2.customer and tmp1.role=tmp2.role
) as userid
FROM temp as tmp2
group by customer,role
order by customer,role
使用虚拟数据创建 SQL
create table temp
(
customer int,
role nvarchar(20),
userid int
)
insert into temp values (1,'Support',123)
insert into temp values (1,'Support',456)
insert into temp values (1,'Procurement',567)
insert into temp values (2,'Support',123)
insert into temp values (2,'Support',456)
insert into temp values (2,'Procurement',888)
insert into temp values (2,'Support',12333)
insert into temp values (2,'Support',45776)
insert into temp values (2,'Procurement',56723)
【问题讨论】:
嗨,MS SQL Server。刚刚标记 【参考方案1】:如果您想避免进入编程用户定义表函数的领域(这是动态生成列所需要的),您可能需要稍微调整您的方法。您没有提及您正在使用哪个 SQL 数据库变体(SQL Server、PostgreSQL、?)。我将假设它支持某种形式的字符串聚合功能(它们几乎都支持),但是这样做的语法会有所不同,因此您可能必须根据您的情况调整代码。您提到角色的数量很少(5-ish?)。建议的解决方案是使用公用表表达式 (CTE) 和 LISTAGG(在其他数据库中命名为 STRING_AGG、GROUP_CONCAT 等)函数生成一个以逗号分隔的用户 ID 列表,每个角色一个。
WITH tsupport
AS (SELECT customer,
Listagg(userid, ',') AS "Support"
FROM temp
WHERE ROLE = 'Support'
GROUP BY customer),
tprocurement
AS (SELECT customer,
Listagg(userid, ',') AS "Procurement"
FROM temp
WHERE ROLE = 'Procurement'
GROUP BY customer)
--> tnextrole...
--> AS (SELECT ... for additional roles
--> Listagg...
SELECT a.customer,
"Support",
"Procurement"
--> "Next Role" etc.
FROM tsupport a
JOIN tprocurement b
ON a.customer = b.customer
--> JOIN tNextRole ...
Fiddle 是 here,根据您的虚拟数据,结果如下所示:
【讨论】:
以上是关于将行值转换为列名的主要内容,如果未能解决你的问题,请参考以下文章