我拥有的:
我有个专栏
ID SerialNo
1 101
2 102
3 103
4 104
5 105
6 116
7 117
8 118
9 119
10 120
这仅仅是10行虚拟行。实际的表有超过10万行。
我想要的东西:
一种类似于任何排序技术的方法或公式,它可以为每个子系列返回SerialNo列的起始元素和结束元素。例如
预期结果: 101-105,115-120
以上结果中的逗号分隔并不重要,只有开始元素和结束元素才是重要的。
我尝试过的:
我是通过PL/SQL编程完成的,我运行了一个循环,在这个循环中,我将开始和结束元素存储在一个表中。但因为没有。对于行(超过100,000),查询执行大约需要2分钟。
我还搜索了SQL Server的一些排序技术,但一无所获。因为呈现每一行所需的时间是排序算法的两倍。
发布于 2016-06-13 08:20:09
只需找到每个系列的开始和结束就很简单了:
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
是一个行,其中没有一个行比当前行少一个行,而一个End
是一个行,其中没有一个行比当前行多一个SerialNo
行。
如果SerialNo
列上没有索引,这可能仍然表现不佳。
结果:
StartSerial EndSerial
----------- -----------
101 105
116 120
希望这是可以接受的,因为您似乎并不关心具体的结果是什么。它也是以设定为基础的。
发布于 2016-06-13 07:17:34
假设每个子系列应该包含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;
https://stackoverflow.com/questions/37783609
复制相似问题