数据序列处理
data sequence handing
我在处理数据序列时遇到了一个奇怪的问题。
我的源数据看起来像 -
Roll-on, Marker
1,1
2,0
3,0
5,1
8,1
9,0
10,1
标记列只能有两个值,1 和 0
如果 roll no 列在序列中,则标记值 1 表示序列的开始,并且所有剩余的 roll no 将在该序列中具有标记值 0。因此,对于第 1-3 卷,第 1 卷的标记值为 1,其余为 0。但是,如果卷号不属于序列(如卷号 8),则标记值为 1。
根据这些数据,我需要创建如下输出 -
Roll range
1
2
3
1-3
5
5-5
8
9
10
8-10
含义-
- 按照输入的顺序显示卷号
- 每个序列结束后,显示一条包含前一个序列的开始和结束卷号的新记录
这怎么可能?
在此先感谢您的帮助。
好像是孤岛和缺口问题
如果我没理解错的话,可以尝试用SUM
window带条件的函数来实现
生成一个行号间隙然后得到 min
和 max
分组依据
SELECT CONCAT(MIN(Roll),'-',MAX(Roll))
FROM (
SELECT *,
SUM(CASE WHEN Marker = 1 THEN 1 ELSE 0 END) OVER(ORDER BY Roll) grp
FROM T
) t1
GROUP BY grp
正如我评论的那样,我不确定 8-10
的逻辑(为什么 8-9
和 10-10
不是来自您的预期结果和列描述,我认为我们可以尝试判断 Roll 的 Max
然后做一些算术。
SELECT CONCAT(MIN(Roll),'-',MAX(Roll))
FROM (
SELECT *,
SUM(CASE WHEN Marker = 1 THEN 1 ELSE 0 END) OVER(ORDER BY Roll) + IIF(MAX(Roll) OVER() = Roll, - Marker,0) grp
FROM T
) t1
GROUP BY grp
以便最终查询合并结果集我们可以使用UNION ALL
;WITH CTE AS (
SELECT *,
SUM(CASE WHEN Marker = 1 THEN 1 ELSE 0 END) OVER(ORDER BY Roll) + IIF(MAX(Roll) OVER() = Roll, - Marker,0) grp
FROM T
)
SELECT [Roll range]
FROM (
SELECT CONCAT(MIN(Roll),'-',MAX(Roll)) 'Roll range',MAX(Roll) seq
FROM CTE t1
GROUP BY grp
UNION ALL
SELECT CAST(Roll AS VARCHAR(5)),Roll
FROM CTE t1
) t1
ORDER BY seq
SELECT
CASE WHEN a=2 AND CHARINDEX('-',R)=0 THEN CONCAT(R,'-',R) ELSE R END as R,
R2,
a
FROM (
SELECT
1 as a,
CONVERT(VARCHAR(3), Roll) R,
Roll as R2
FROM table1
UNION ALL
SELECT
2,
STRING_AGG(Roll,'-') R,
MAX(Roll) as R2
FROM (
SELECT
Roll,
SUM(Marker) OVER (ORDER BY Roll) S
FROM
table1
) x
GROUP BY S
) x
ORDER BY R2,a
输出:
R
R2
a
1
1
1
2
2
1
3
3
1
1-2-3
3
2
5
5
1
5-5
5
2
8
8
1
9
9
1
8-9
9
2
10
10
1
10-10
10
2
- 已添加列
R2
和 a
以进行正确排序。
- 我将
8-9
和 10-10
分组,但这个问题仍然悬而未决,请参阅评论
我在处理数据序列时遇到了一个奇怪的问题。 我的源数据看起来像 -
Roll-on, Marker
1,1
2,0
3,0
5,1
8,1
9,0
10,1
标记列只能有两个值,1 和 0
如果 roll no 列在序列中,则标记值 1 表示序列的开始,并且所有剩余的 roll no 将在该序列中具有标记值 0。因此,对于第 1-3 卷,第 1 卷的标记值为 1,其余为 0。但是,如果卷号不属于序列(如卷号 8),则标记值为 1。 根据这些数据,我需要创建如下输出 -
Roll range
1
2
3
1-3
5
5-5
8
9
10
8-10
含义-
- 按照输入的顺序显示卷号
- 每个序列结束后,显示一条包含前一个序列的开始和结束卷号的新记录
这怎么可能?
在此先感谢您的帮助。
好像是孤岛和缺口问题
如果我没理解错的话,可以尝试用SUM
window带条件的函数来实现
生成一个行号间隙然后得到 min
和 max
分组依据
SELECT CONCAT(MIN(Roll),'-',MAX(Roll))
FROM (
SELECT *,
SUM(CASE WHEN Marker = 1 THEN 1 ELSE 0 END) OVER(ORDER BY Roll) grp
FROM T
) t1
GROUP BY grp
正如我评论的那样,我不确定 8-10
的逻辑(为什么 8-9
和 10-10
不是来自您的预期结果和列描述,我认为我们可以尝试判断 Roll 的 Max
然后做一些算术。
SELECT CONCAT(MIN(Roll),'-',MAX(Roll))
FROM (
SELECT *,
SUM(CASE WHEN Marker = 1 THEN 1 ELSE 0 END) OVER(ORDER BY Roll) + IIF(MAX(Roll) OVER() = Roll, - Marker,0) grp
FROM T
) t1
GROUP BY grp
以便最终查询合并结果集我们可以使用UNION ALL
;WITH CTE AS (
SELECT *,
SUM(CASE WHEN Marker = 1 THEN 1 ELSE 0 END) OVER(ORDER BY Roll) + IIF(MAX(Roll) OVER() = Roll, - Marker,0) grp
FROM T
)
SELECT [Roll range]
FROM (
SELECT CONCAT(MIN(Roll),'-',MAX(Roll)) 'Roll range',MAX(Roll) seq
FROM CTE t1
GROUP BY grp
UNION ALL
SELECT CAST(Roll AS VARCHAR(5)),Roll
FROM CTE t1
) t1
ORDER BY seq
SELECT
CASE WHEN a=2 AND CHARINDEX('-',R)=0 THEN CONCAT(R,'-',R) ELSE R END as R,
R2,
a
FROM (
SELECT
1 as a,
CONVERT(VARCHAR(3), Roll) R,
Roll as R2
FROM table1
UNION ALL
SELECT
2,
STRING_AGG(Roll,'-') R,
MAX(Roll) as R2
FROM (
SELECT
Roll,
SUM(Marker) OVER (ORDER BY Roll) S
FROM
table1
) x
GROUP BY S
) x
ORDER BY R2,a
输出:
R | R2 | a |
---|---|---|
1 | 1 | 1 |
2 | 2 | 1 |
3 | 3 | 1 |
1-2-3 | 3 | 2 |
5 | 5 | 1 |
5-5 | 5 | 2 |
8 | 8 | 1 |
9 | 9 | 1 |
8-9 | 9 | 2 |
10 | 10 | 1 |
10-10 | 10 | 2 |
- 已添加列
R2
和a
以进行正确排序。 - 我将
8-9
和10-10
分组,但这个问题仍然悬而未决,请参阅评论