我有一张表格,其中单个用户的数据是这样的
ID - 数字 - 子编号 - 名称
1 101 201101 Jack
2 101 201102 Jack
3 101 201103 Jack
4 101 201107 Jack
5 101 201111 Jack
6 101 201112 Jack
7 101 201113 Jack
8 101 201161 Jack
9 101 201162 Jack
10 101 201163 Jack
11 101 201164 Jack
12 101 201165 Jack
我想获得这样的记录without using any kind of loop.
数字 - 名称 - 子编号
101 Jack (201101-201103, 201107, 201111-201113, 201161-201165)
目前我能够以此
的形式获取记录数字 - 名称 - 子编号
101 Jack (201101,201102,201103, 201107, 201111,201112,201113, 201161,201162,201163,201164,201165)
查询以获得更高的结果是
SELECT Number, Name
,STUFF((SELECT ', ' + CAST(SubNumber AS VARCHAR(50)) [text()]
FROM [Table]
WHERE Number= t.Number
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') SubNumber
FROM [Table] t
GROUP BY Number,Name
having Number= '101'
我完全被困在这里。任何形式的帮助将不胜感激。
答案 0 :(得分:1)
试试这个。对于MS SQL Server 2012 +:
DECLARE @t TABLE
(
ID INT ,
Number INT ,
Code INT
)
INSERT INTO @t
VALUES ( 1, 201101, 101 ),
( 2, 201102, 101 ),
( 3, 201103, 101 ),
( 4, 201107, 101 ),
( 5, 201111, 101 ),
( 6, 201112, 101 ),
( 7, 201113, 101 ),
( 8, 201161, 101 ),
( 9, 201162, 101 ),
( 10, 201163, 101 ),
( 11, 201164, 101 ),
( 12, 201165, 101 ),
( 13, 201166, 102 ),
( 14, 201169, 102 ),
( 15, 201175, 102 ),
( 16, 201176, 102 ),
( 17, 201177, 102 );
WITH cte1
AS ( SELECT * ,
CASE WHEN number
- LAG(Number) OVER ( PARTITION BY Code ORDER BY ID ) = 1
THEN 0
ELSE 1
END AS lg
FROM @t
),
cte2
AS ( SELECT * ,
SUM(lg) OVER ( PARTITION BY Code ORDER BY ID ) AS s
FROM cte1
),
cte3
AS ( SELECT * ,
MIN(Number) OVER ( PARTITION BY Code, s ) AS mi ,
MAX(Number) OVER ( PARTITION BY Code, s ) AS ma
FROM cte2
),
cte4
AS ( SELECT Code ,
mi ,
ma
FROM cte3
GROUP BY Code ,
mi ,
ma
)
SELECT code ,
STUFF((SELECT ', '
+ CASE WHEN mi <> ma
THEN CAST(mi AS NVARCHAR(MAX)) + '-'
+ CAST(ma AS NVARCHAR(MAX))
ELSE CAST(mi AS NVARCHAR(MAX))
END
FROM cte4
WHERE Code = t.Code
FOR XML PATH('') ,
TYPE)
.value('.', 'NVARCHAR(MAX)'), 1, 2, '') AS Number
FROM cte4 t
GROUP BY Code
输出:
code Number
101 201101-201103, 201107, 201111-201113, 201161-201165
102 201166, 201169, 201175-201177
答案 1 :(得分:0)
首先,您应该为每个时间间隔选择开始和结束(请参阅CT
- 视图),然后为每个时间间隔使用格式START-FINISH
形成字符串(请参阅CT2
视图)。在这里你还应该处理start = finish的情况(参见CASE
语句)。然后使用您的查询为每个Name分组和连接字符串。
WITH CT AS
(
SELECT Id,Number, SubNumber as StartNum, Null As EndNumber, Name
FROM T
WHERE NOT EXISTS (SELECT SubNumber FROM T as T1
WHERE T1.Number=T.Number AND T1.SubNumber+1=T.Subnumber)
UNION
SELECT Id,Number,Null as StartNum, SubNumber As EndNumber, Name
FROM T
WHERE NOT EXISTS (SELECT SubNumber FROM T as T1
WHERE T1.Number=T.Number AND T1.SubNumber-1=T.Subnumber)
),
CT2 AS
(
SELECT ID,Number,
CAST(StartNum AS VARCHAR(50))
+ (SELECT TOP 1
CASE WHEN T3.EndNumber = CT.StartNum
THEN ''
ELSE '-' +CAST(T3.EndNumber AS VARCHAR(50))
END
FROM CT as T3
WHERE T3.Number=CT.Number
AND T3.EndNumber>=CT.StartNum
ORDER BY EndNumber) as SubNumber
,Name
FROM CT
WHERE EndNumber IS NULL
)
SELECT Number, Name
,STUFF((SELECT ', ' + SubNumber [text()]
FROM CT2
WHERE Number= t.Number
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') SubNumber
FROM CT2 t
GROUP BY Number,Name
HAVING Number= '101'