我有什么:
我有一个专栏
ID SerialNo
1 101
2 102
3 103
4 104
5 105
6 116
7 117
8 118
9 119
10 120
这些只是10个虚拟行。实际的表有超过100 000行。
我想得到什么:
像任何排序技术一样的方法或公式,它可以为每个子系列返回[SerialNo]列的起始和结束元素。例如
预期成果:101-105,115-120
上述结果中的逗号分隔并不重要,只有起始和结束元素很重要。
我尝试了什么:
我是通过PL / SQL编程实现的,通过运行一个循环,我将开始和结束元素存储在一个TABLE中。 但由于没有。行(超过100 000)查询执行大约需要2分钟。
我还搜索了SQL Server的一些排序技术,但我一无所获。因为渲染每一行所需的时间是排序算法的两倍
答案 0 :(得分:1)
假设每个子系列应该包含5个记录,我使用下面的sql得到了预期的结果。我希望这会有所帮助。
DECLARE @subSeriesRange INT=5;
CREATE TABLE #Temp(ID INT,SerialNo INT);
INSERT INTO #Temp VALUES(1,101),
(2,102),
(3,103),
(4,104),
(5,105),
(6,116),
(7,117),
(8,115),
(9,119),
(10,120);
SELECT STUFF((SELECT CONCAT(CASE ID%@subSeriesRange WHEN 1 THEN ',' ELSE '-' END,SerialNo)
FROM #Temp
WHERE ID%@subSeriesRange = 1 OR ID%@subSeriesRange=0
ORDER BY ID
FOR XML PATH('')),1,1,''
);
DROP TABLE #Temp;
答案 1 :(得分:0)
只是找到每个系列的开头和结尾非常简单:
declare @t table (ID int not null, SerialNo int not null)
insert into @t(ID,SerialNo) values
(1 ,101), (2 ,102), (3 ,103),
(4 ,104), (5 ,105), (6 ,116),
(7 ,117), (8 ,118), (9 ,119),
(10,120)
;With Starts as (
select t1.SerialNo,ROW_NUMBER() OVER (ORDER BY t1.SerialNo) as rn
from
@t t1
left join
@t t1_no
on t1.SerialNo = t1_no.SerialNo + 1
where t1_no.ID is null
), Ends as (
select t1.SerialNo,ROW_NUMBER() OVER (ORDER BY t1.SerialNo) as rn
from
@t t1
left join
@t t1_no
on t1.SerialNo = t1_no.SerialNo - 1
where t1_no.ID is null
)
select
s.SerialNo as StartSerial,
e.SerialNo as EndSerial
from
Starts s
inner join
Ends e
on s.rn = e.rn
逻辑是Start
是一行,其中没有行SerialNo
小于当前行,而End
是没有行的行比当前行多SerialNo
一行的行。
如果SerialNo
列上没有索引,这可能仍会表现不佳。
结果:
StartSerial EndSerial
----------- -----------
101 105
116 120
希望这是可以接受的,因为您似乎并不关心特定结果的样子。它也保持基于集合。