将sql server中的值连接起来,并按另一个值(ms sql server)分组
我有简单的选择将sql server中的值连接起来,并按另一个值(ms sql server)分组,sql,sql-server,Sql,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
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中执行此操作吗 下面的代码片段适合您-
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;
如果您使用的是SQL Server 2017,则可以使用新函数STRING_AGG:
请注意,您的表中没有排序,因此不能为“User2”保留“Company3,Company6,Company1,Company5”的顺序,除非您有其他列可供排序。另一种不需要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
是的。到目前为止,您尝试了什么?您使用的是哪个版本的SQL Server?可能与我使用的SQL Server 2014重复。目前我正在尝试使用COALESCE。它可以工作,但我不能按用户正确分组,因为仍然有用户重复值它查询结果可能重复Wow。如果你不介意的话,告诉我在2016年、2017年,我从哪里可以用新的t-sql函数更新自己?@PrabhatG有一个简单的例子。Microsoft发布每一版本的文档,介绍最新内容。该链接的第一个非广告结果是2016年的新功能。我知道。我以为你有什么博客或者其他什么东西info@PrabhatG没有,我通常只是在新版发布时看一下发行说明;但也要注意来自SQLServerCentral和BrentOzar等网站的邮件列表。我肯定有博客,但是,我个人没有任何链接。文档非常详尽,而SQL Server中的循环天生就很慢。一个数据集是一种更有效的方法。我同意,它也可以在一个基于循环的需要的基础上完成,虽然在小的情况下,很少的用户循环不是那么差。只是想注意,除了XML路径之外的其他解决方案是可以考虑的。
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
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