[英]Concatenate values in sql server and group by another value | ms sql server
我有簡單的選擇
select distinct UserName, Company from Users inner join Companies on Users.UserName = Companies.UserFullName
查詢結果如下:
User1 | Company1
User1 | Company2
User1 | Company3
User1 | Company4
User2 | Company3
User2 | Company6
User2 | Company1
User2 | Company5
我想連接公司值並按用戶分組。 像這樣:
User1 | Company1 , Company2 , Company3 , Company4
User2 | Company3 , Company6 , Company1 , Company5
是否有可能在sql server中做?
如果您使用的是SQL Server 2017,則可以使用新功能STRING_AGG
:
SELECT UserName,
STRING_AGG(Company,' , ') WITHIN GROUP (ORDER BY Company) AS Companies
FROM #T1
GROUP BY Username;
請注意,您的表中沒有排序,因此,除非您有其他要排序的列,否則不能為'User2'
保留'Company3, Company6, Company1, Company5'
順序。
以下代碼段適用於您-
CREATE TABLE #t1 (UserName VARCHAR(100), Company VARCHAR(100));
INSERT #t1 values ('User1','Company1');
INSERT #t1 values ('User1','Company2');
INSERT #t1 values ('User1','Company3');
INSERT #t1 values ('User1','Company4');
INSERT #t1 values ('User2','Company3');
INSERT #t1 values ('User2','Company6');
INSERT #t1 values ('User2','Company1');
INSERT #t1 values ('User2','Company5');
GO
select
UserName,
stuff((
select ',' + t.[Company]
from #t1 t
where t.UserName = #t1.UserName
order by t.[Company]
for xml path('')
),1,1,'') as CompanyName
from #t1
group by UserName;
另一個不需要FOR XML PATH
子句的解決方案此解決方案基於循環
SET NOCOUNT ON
IF OBJECT_ID ('tempdb..#t1') IS NOT NULL DROP TABLE #T1;
IF OBJECT_ID ('tempdb..#t2') IS NOT NULL DROP TABLE #T2;
CREATE TABLE #t1 (UserName VARCHAR(100), Company VARCHAR(100));
INSERT #t1 values ('User1','Company1');
INSERT #t1 values ('User1','Company2');
INSERT #t1 values ('User1','Company3');
INSERT #t1 values ('User1','Company4');
INSERT #t1 values ('User2','Company3');
INSERT #t1 values ('User2','Company6');
INSERT #t1 values ('User2','Company1');
INSERT #t1 values ('User2','Company5');
GO
DECLARE @Table TABLE (UserName VARCHAR(100), Combined VARCHAR(4000))
DECLARE @i INT = 1
SELECT DENSE_RANK () OVER (ORDER BY UserName) Seq, *
INTO #T2
FROM #t1
WHILE @i <= (SELECT MAX(Seq) FROM #T2)
BEGIN
DECLARE @ConcatedCompany VARCHAR(4000) = ''
SELECT @ConcatedCompany+= ',' + Company
FROM #T2
WHERE Seq = @i
INSERT INTO @Table (UserName , Combined)
SELECT UserName , STUFF(@ConcatedCompany,1,1,'')
FROM #T2
WHERE Seq = @i
GROUP BY UserName
SET @i +=1
END
SELECT *
FROM @Table
UPDATE!
Larnu關於性能的評論是一個很好的觀點,通常我會避免使用WHILE循環,而應該考慮基於集合的操作,因此,這里是沒有循環且沒有“ FOR XML PATH”的解決方案
SET NOCOUNT ON
IF OBJECT_ID ('tempdb..#t1') IS NOT NULL DROP TABLE #T1
IF OBJECT_ID ('tempdb..##T2') IS NOT NULL DROP TABLE ##T2
IF OBJECT_ID ('tempdb..##Table') IS NOT NULL DROP TABLE ##Table
CREATE TABLE #t1 (UserName VARCHAR(100), Company VARCHAR(100));
INSERT #t1 values ('User1','Company1');
INSERT #t1 values ('User1','Company2');
INSERT #t1 values ('User1','Company3');
INSERT #t1 values ('User1','Company4');
INSERT #t1 values ('User2','Company3');
INSERT #t1 values ('User2','Company6');
INSERT #t1 values ('User2','Company1');
INSERT #t1 values ('User2','Company5');
GO
CREATE TABLE ##Table (UserName nvarchar(50), Combined nvarchar(4000))
SELECT DENSE_RANK () OVER (ORDER BY UserName) Seq, *
INTO ##T2
FROM #t1
DECLARE @cmd NVARCHAR(MAX) =''
;WITH T2 (Seq) AS
(
SELECT DISTINCT Seq
FROM ##T2
)
SELECT @cmd += 'DECLARE @ConcatedCompany'+CONVERT(VARCHAR(10),Seq)+' NVARCHAR(4000) = ''''
SELECT @ConcatedCompany'+CONVERT(VARCHAR(10),Seq)+' += '','' + Company FROM ##T2 WHERE Seq = '+CONVERT(VARCHAR(10),Seq)+ CHAR(10)+
' INSERT INTO ##Table (UserName, Combined)
SELECT UserName , STUFF(@ConcatedCompany'+CONVERT(VARCHAR(10),Seq)+',1,1,'''')
FROM ##T2 WHERE Seq = '+CONVERT(VARCHAR(10),Seq) + CHAR(10)+
' GROUP BY UserName '+CHAR(10)+
';'
+CHAR(10)
FROM T2
EXEC sp_executesql @Cmd
SELECT UserName , Combined
FROM ##Table
DROP TABLE ##Table
DROP TABLE ##T2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.