从范围列表中创建数字列表

时间:2015-06-02 16:20:29

标签: sql sql-server

我有一个包含两列的表,其中包含整数序列的开头和结尾。这是一个很大的列表,但我很确定任何范围都没有重叠。我想生成这些范围开始和结束范围内包含的所有数字的列表。

基本上我想做与此问题相反的事:How to create number ranges from a list of numbers?

根据我的阅读,我对解决方案的最佳猜测可能是某种动态交叉应用,但我不确定如何开始这样做。

我的表看起来像这样:

表格

RangeStart RangeEnd
200        205
208        209
221        221
222        224

我想要这样的事情:

期望的结果

Sequence
200
201
202
203
204
205
208
209
221
222
223
224

3 个答案:

答案 0 :(得分:0)

最简单的方法是从一个整数列表开始。一个方便的 - 如果列表不是太长 - 是master..spt_values

with n as (
      select row_number() over (order by (select null)) - 1 as n
      from master..spt_values
     )
select (rangestart + n.n) as sequence
from ranges r join
     n
     on r.rangestart + n.n <= r.rangeend
order by sequence;

如果您担心重叠,那么以下是获取序列的简便方法:

select distinct (rangestart + n.n) as sequence
from ranges r join
     n
     on r.rangestart + n.n <= r.rangeend
order by sequence;

如果问题有很多重叠和值,那么你会想要一个不同的方法(但这不是你要问的问题)。

答案 1 :(得分:0)

declare @Sequence table(
  Value int
)

declare @Value int = 0

while (@Value < 500)
  begin
    insert @Sequence values(@Value)
    select @Value += 1
  end

select * from @Sequence

declare @Ranges table(
  RangeStart int,
  RangeEnd int
)

insert into @Ranges values(200, 205)
insert into @Ranges values(208, 209)
insert into @Ranges values(221, 221)
insert into @Ranges values(222, 224)


select s.Value
from @Sequence s
join @Ranges r on r.RangeStart <= s.Value and r.RangeEnd >= s.Value
order by s.Value

关键是获取@Sequence值列表。

答案 2 :(得分:0)

您可以避免使用&#39;数字&#39;表,通过使用递归公用表表达式:

WITH Numbers AS (
SELECT RangeStart, RangeStart AS Number, RangeEnd from RangeTable
UNION ALL
SELECT RangeStart, Number + 1, RangeEnd FROM Numbers WHERE Number < RangeEnd)
SELECT Number FROM Numbers ORDER BY Number

第一部分是&#39;锚点&#39; query,定义根成员(在本例中,是数字的范围,范围中的第一个数字,以及数字的范围)。

第二部分(在UNION ALL之后)以递归方式连接到锚成员,并且基本上不断向Number添加一个并递归,直到它到达RangeEnd

最后一部分只得到我们建立的CTE的数字(我们不再对范围的开始和结束感兴趣)并确保它们的顺序正确(这对你来说可能无关紧要,在这种情况下你可以省略ORDER BY子句。)

编辑 - 如果您使用此命令达到递归限制,可以通过在查询末尾添加OPTION (MAXRECURSION 0)来解决此问题。抱怨错过了这个!