我有一个包含两列的表,其中包含整数序列的开头和结尾。这是一个很大的列表,但我很确定任何范围都没有重叠。我想生成这些范围开始和结束范围内包含的所有数字的列表。
基本上我想做与此问题相反的事: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
答案 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)
来解决此问题。抱怨错过了这个!