在SQL Server中检索已排序的列值

时间:2016-06-13 07:03:42

标签: sql-server sorting sql-server-2012

我有什么:

我有一个专栏

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的一些排序技术,但我一无所获。因为渲染每一行所需的时间是排序算法的两倍

2 个答案:

答案 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

希望这是可以接受的,因为您似乎并不关心特定结果的样子。它也保持基于集合。