tsql - 如何在行号之间添加破折号,在非行号之间添加逗号
问题描述
我想在适当的地方用逗号和连字符替换一组运行和非运行数字。
使用STUFF
&XML PATH
我能够通过获得类似1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13, 15, 19, 20, 21, 22, 24
.
WITH CTE AS (
SELECT DISTINCT t1.ORDERNo, t1.Part, t2.LineNum
FROM [DBName].[DBA].Table1 t1
JOIN Table2 t2 ON t2.Part = t1.Part
WHERE t1.ORDERNo = 'AB12345')
SELECT c1.ORDERNo, c1.Part, STUFF((SELECT ', ' + CAST(LineNum AS VARCHAR(5))
FROM CTE c2
WHERE c2.ORDERNo= c1.ORDERNo
FOR XML PATH('')), 1, 2, '') AS [LineNums]
FROM CTE c1
GROUP BY c1.ORDERNo, c1.Part
这是一些示例输出:
ORDERNo Part LineNums
ON5650 PT01-0181 5, 6, 7, 8, 12
ON5652 PT01-0181 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13, 15, 19, 20, 21, 22, 24
ON5654 PT01-0181 1, 4
ON5656 PT01-0181 1, 2, 4
ON5730 PT01-0181 1, 2
ON5253 PT16-3934 1, 2, 3, 4, 5
ON1723 PT02-0585 1, 2, 3, 6, 8, 9, 10
想拥有:
OrderNo Part LineNums
ON5650 PT01-0181 5-8, 12
ON5652 PT01-0181 1-10, 13, 15, 19-22, 24
ON5654 PT01-0181 1, 4
ON5656 PT01-0181 1-2, 4
ON5730 PT01-0181 1-2
ON5253 PT16-3934 1-5
ON1723 PT02-0585 1-3, 6, 8-10
解决方案
这是一个典型的差距和孤岛问题。
(关于这个主题的好读物是来自 SQL Server MVP Deep Dives的 Itzik Ben-Gan 的Gaps and island)
这个想法是您首先需要识别连续数字组。一旦你做到了,剩下的就很容易了。
首先,创建并填充示例表(请在以后的问题中保存我们这一步):
DECLARE @T AS TABLE
(
N int
);
INSERT INTO @T VALUES
(1), (2), (3), (4),
(6),
(8),
(10), (11),
(13), (14), (15),
(17),
(19), (20), (21),
(25);
然后,使用公用表表达式来标识组。
With Grouped AS
(
SELECT N,
N - ROW_NUMBER() OVER(ORDER BY N) As Grp
FROM @T
)
如果这个 cte 是这样的结果:
N Grp
1 0
2 0
3 0
4 0
6 1
8 2
10 3
11 3
13 4
14 4
15 4
17 5
19 6
20 6
21 6
25 9
如您所见,虽然数字是连续的,但grp
值保持不变。
当一行的数字与前一个数字不连续时,该grp
值会发生变化。
然后,您从该 cte 中进行选择,使用case
表达式选择单个数字(如果它是其组中唯一的数字)或组的开始和结束,用破折号分隔:
SELECT STUFF(
(
SELECT ', ' +
CASE WHEN MIN(N) = MAX(N) THEN CAST(MIN(N) as varchar(11))
ELSE CAST(MIN(N) as varchar(11)) +'-' + CAST(MAX(N) as varchar(11))
END
FROM Grouped
GROUP BY grp
FOR XML PATH('')
), 1, 2, '') As GapsAndIslands
结果:
GapsAndIslands
1-4, 6, 8, 10-11, 13-15, 17, 19-21, 25
推荐阅读
- matplotlib - 什么是子图零?(缺乏文件)
- php - Composer 无法在没有 root 的情况下执行命令
- perl - Perl中如何将一个值压入数组?
- python - 按条件查找数据框中行和列的所有索引
- python - 使用 Celery 注册多个任务
- javascript - 使用 RegEx 和 Quill JS 将一组禁用词加粗?
- oracle - 使用 Oracle MERGE INTO 将两个表中的数据合并到第三个表中
- c# - 使用 Span 的 Base64 编码
在 dotnetcore 2.1 - angular - 在触发承诺后从 catch 子句访问“this”
- html - 如何删除图像创建的空白?