我有一张客户联系人及其角色的表格。下面是简化的示例。
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)
答案 0 :(得分:0)
如果要避免进入对用户定义的表函数进行编程的领域(这是动态生成列所需要的),则可能需要稍微调整一下方法。您没有提到正在使用哪个SQL数据库变体(SQL Server,PostgreSQL 、?)。我将假设它支持某种形式的字符串聚合功能(它们几乎都支持),但是这样做的语法会有所不同,因此您可能必须根据情况调整代码。您提到角色数量很少(5英镑?)。提议的解决方案是使用公用表表达式(CTE)和LISTAGG(在其他数据库中分别命名为STRING_AGG,GROUP_CONCAT等)函数来生成用逗号分隔的用户ID列表,每个角色一个用户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 ...
提琴是here,根据您的虚拟数据,结果如下所示: