我有一个表格,如下所示:
DECLARE @T AS TABLE
(
SeqNumber INT,
Note VARCHAR(MAX),
UserID INT
)
INSERT INTO @T (SeqNumber, Note, UserID) VALUES
(1, 'A', 20),
(2, 'B', 20),
(1, 'F', 20),
(2, 'K', 20),
(3, 'M', 20),
(1, 'X', 20),
(1, 'Y', 20)
我希望创建如下结果:
UserID ResultNotes
20 'AB'
20 'FKM'
20 'X'
20 'Y'
您知道如何在MS SQL Server(T-SQL)中实现吗?它可以在MS SQL Server 2016或更早版本中。
谢谢
答案 0 :(得分:3)
那是一开始的评论,但我决定为此准备一个答案...
您知道吗,没有隐式排序顺序?当SeqNumber为1
时,您似乎想启动一个新组。因此-在您的样本中-A和B是第一组,FKM是第二组,依此类推。但是,如果没有其他排序顺序或任何类型的分组键,则该集合将不会被排序!。这可能会以任意顺序返回...
这是使用STRING_AGG
(needs v2017+)进行分组的方法:
DECLARE @T AS TABLE
(
GroupKey INT,
SeqNumber INT,
Note VARCHAR(MAX),
UserID INT
)
INSERT INTO @T (GroupKey,SeqNumber, Note, UserID) VALUES
(1, 1, 'A', 20),
(1, 2, 'B', 20),
(2, 1, 'F', 20),
(2, 2, 'K', 20),
(2, 3, 'M', 20),
(3, 1, 'X', 20),
(4, 1, 'Y', 20);
SELECT t.UserID
,STRING_AGG(Note,'') WITHIN GROUP(ORDER BY t.SeqNumber) AS ResultNotes
FROM @T t
GROUP BY t.GroupKey,t.UserID;
这适用于2017年之前的版本:
SELECT t.UserID
,(
SELECT t2.Note AS [*]
FROM @T t2
WHERE t.GroupKey=t2.GroupKey
AND t.UserID=t2.UserID
ORDER BY t2.SeqNumber
FOR XML PATH(''),TYPE
).value('.','nvarchar(max)') AS ResultNotes
FROM @T t
GROUP BY t.GroupKey,t.UserID
如果排序顺序是固定的(在我的情况下为IDENTITY
-ID),请参见以下代码如何创建分组密钥:
DECLARE @T AS TABLE
(
ID INT IDENTITY,
SeqNumber INT,
Note VARCHAR(MAX),
UserID INT
)
INSERT INTO @T (SeqNumber, Note, UserID) VALUES
(1, 'A', 20),
(2, 'B', 20),
(1, 'F', 20),
(2, 'K', 20),
(3, 'M', 20),
(1, 'X', 20),
(1, 'Y', 20);
WITH Get1s AS --set a group key per "1"
(
SELECT t.ID,ROW_NUMBER() OVER(ORDER BY ID) AS GroupKey
FROM @T t
WHERE t.SeqNumber=1
)
SELECT *
,(SELECT MAX(x.GroupKey) FROM Get1s x WHERE t.ID>=x.ID) AS GroupKey
FROM @T t;
下一步,您可以按上述方法使用此分组键...
答案 1 :(得分:0)
DECLARE @T AS TABLE
(
SeqNumber INT,
Note VARCHAR(MAX),
UserID INT
)
INSERT INTO @T (SeqNumber, Note, UserID) VALUES
(1, 'A', 20),
(2, 'B', 20),
(1, 'F', 20),
(2, 'K', 20),
(3, 'M', 20),
(1, 'X', 20),
(1, 'Y', 20)
drop table if exists #d
select ROW_NUMBER() OVER(ORDER BY userid ASC) AS Row#, case when SeqNumber = 1 then 1 else 0 end as t , SeqNumber,note,userid into #d from @t
select userid,string_agg(Note,'') from
(
select isnull(t + (select sum(t) from #d as g where g.row# < #d.row#),1) as s , SeqNumber,note,userid from #d
) j
group by s,userid
答案 2 :(得分:0)
您可以尝试以下操作:
如果seqNum以1开头并以1递增,则此解决方案将起作用
DECLARE @T AS TABLE
(
SeqNumber INT,
Note VARCHAR(MAX),
UserID INT
)
INSERT INTO @T (SeqNumber, Note, UserID) VALUES
(1, 'A', 20),
(2, 'B', 20),
(3, 'C', 20),
(4, 'D', 20),
(5, 'E', 20),
(1, 'F', 20),
(2, 'K', 20),
(3, 'M', 20),
(1, 'X', 20),
(1, 'Y', 20)
;with cte1 as
(
select *,
CASE WHEN LEAD(SeqNumber) OVER(partition by userId order by (select null))>SeqNumber THEN LEAD(SeqNumber) OVER(order by (select null))
ELSE NULL END as leadingSeq,
ROW_NUMBER()over(partition by userId order by (select null)) as rowNum
from @T
)
,
cte2
As
(
select c1.SeqNumber,c1.UserId,ISNULL(c1.Note,'')+ISNULL(c2.Note,'') as Note
,c2.leadingSeq,c2.rowNum
from cte1 c1
LEFT JOIN cte1 c2 on c1.leadingSeq=c2.SeqNumber and c2.rowNum=c1.rowNum+1 and c1.SeqNumber=1
Where c1.SeqNumber=1
or c2.Note IS NOT NULL
Union All
Select c1.SeqNumber,c1.UserId,ISNULL(c1.Note,'')+ISNULL(c2.Note,'') as SecNote
,c2.leadingSeq,c2.rowNum
from cte2 c1
JOIN cte1 c2 on c1.leadingSeq=c2.SeqNumber and c2.rowNum=c1.rowNum+1
)
select UserId,Note
from cte2
where leadingSeq is null