【发布时间】:2011-01-10 12:52:48
【问题描述】:
我有一张桌子
列:姓名、角色、部门
一个人可以有很多角色。因此,在检索数据时,如果一个人拥有多个角色,我希望角色列在 CSV 中。
Name Role Dept
jose Role1,Role2 PWD
假设除了记录的角色之外的所有其他细节都是相同的。
谢谢
【问题讨论】:
标签: sql sql-server-2005 tsql stored-procedures
我有一张桌子
列:姓名、角色、部门
一个人可以有很多角色。因此,在检索数据时,如果一个人拥有多个角色,我希望角色列在 CSV 中。
Name Role Dept
jose Role1,Role2 PWD
假设除了记录的角色之外的所有其他细节都是相同的。
谢谢
【问题讨论】:
标签: sql sql-server-2005 tsql stored-procedures
这将为您解决问题。
select
t3.Name,
left(t3.Roles, len(t3.Roles)-1) as Roles,
t3.Dept
from
(select
t2.Name,
t2.Dept,
(select t1.[Role] + ','
from Table1 as t1
where
t1.Name = t2.Name and
t1.Dept = t2.Dept
order by t1.[Role]
for xml path('')) as Roles
from Table1 as t2
group by t2.Name, t2.Dept) as t3
这取自此页面的“黑盒 XML 方法”中的第一个示例 https://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/
内部查询将角色列表构建为 xml。 xml path('') 参数为空,因此您不会获得 xml 标记,而只能获得逗号分隔的列表。
外部查询仅用于删除每行末尾的逗号。
Group by t2.Name, t2.Dept 确保您只会为 Name+Dept 的每个唯一组合获得一行。
【讨论】:
一种选择是使用递归参数和游标来实现。试试这个查询:
DECLARE @Name varchar(50), @Role varchar(MAX), @Dept varchar(50)
DECLARE role_cursor CURSOR FOR
SELECT Name,min(Dept)
FROM [dbo].[Table_1]
group by Name
OPEN role_cursor;
FETCH NEXT FROM role_cursor
INTO @Name, @Dept
WHILE @@FETCH_STATUS = 0
BEGIN
set @Role = ''
select @Role = @Role+[Role]+','
FROM [dbo].[Table_1]
where Name=@Name
select @Name,left(@Role,len(@Role)-1),@Dept
FETCH NEXT FROM role_cursor
INTO @Name, @Dept
END
CLOSE role_cursor;
DEALLOCATE role_cursor;
一旦你有了它,你就可以在选择之前使用插入来在结果表中插入值
【讨论】:
您可以创建用户定义的聚合函数,生成以逗号分隔的值列表,并可在查询中用作任何其他聚合函数(即MIN、MAX、@ 987654324@等)。
这是我博客中的相关帖子:A SQL CLR user-defined aggregate - notes on creating and debugging
创建dbo.Concat 函数后,您将能够执行以下查询:
SELECT
Name
, Dept
, dbo.Concat(Role) AS Roles
FROM dbo.Table_1
GROUP BY
Name
, Dept
我在生产环境中使用了几年,它的性能非常好,即使处理了大量的行。
【讨论】: