Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从范围列表创建数字列表_Sql_Sql Server - Fatal编程技术网

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

Sql 从范围列表创建数字列表,sql,sql-server,Sql,Sql Server,我有一个包含两列的表,其中包含整数序列的开始和结束。这是一个很大的列表,但我很确定在任何范围内都没有重叠。我想生成一个包含在这些范围开始和结束边界内的所有数字的列表 基本上我想做与这个问题相反的事情: 从我所读到的内容来看,我对解决方案的最佳猜测可能是某种动态交叉应用,但我甚至不确定如何开始 我的桌子看起来像这样: 桌子 我想要这样的东西: 期望结果 最简单的方法是从整数列表开始。如果列表不太长,一个方便的选项是master..spt_值: 如果您担心重叠,那么以下是获取序列的简单方法: sel

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

基本上我想做与这个问题相反的事情:

从我所读到的内容来看,我对解决方案的最佳猜测可能是某种动态交叉应用,但我甚至不确定如何开始

我的桌子看起来像这样:

桌子

我想要这样的东西:

期望结果


最简单的方法是从整数列表开始。如果列表不太长,一个方便的选项是master..spt_值:

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

select distinct (rangestart + n.n) as sequence
from ranges r join
     n
     on r.rangestart + n.n <= r.rangeend
order by sequence;
如果问题有很多重叠和值,那么您可能需要一种稍微不同的方法,但这不是您要问的问题

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值的列表。

通过使用递归公共表表达式,可以避免使用“数字”表:

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
第一部分是“anchor”查询,它定义了本例中的根成员、从number开始的范围、范围中的第一个数字以及到number的范围

并集后的第二部分全部递归地连接到锚定成员,并且基本上一直将一添加到Number并递归,直到到达RangeEnd

最后一部分仅从我们构建的CTE中获取数字,我们不再对范围开始和结束感兴趣,并确保它们的顺序正确。这可能对您不重要,在这种情况下,您可以省略order BY子句


编辑-如果使用此选项达到递归限制,可以通过在查询末尾添加选项MAXRECURSION 0来修复此问题。抱歉错过了这个

你想用sql来做这件事是因为?@草莓如果你唯一的工具是锤子…我喜欢这个,但是你可能会遇到最大递归的问题。。。Msg 530,16级,状态1,第13行语句终止。最大递归100在语句完成之前就已经用尽了。我可以补充一点,使用CTE以这种方式生成数字范围有几个优点,其中最重要的一点是它不依赖于任何“数字表”的存在或可访问性。这里对生成范围的各种方法进行了很好的讨论:@crapycodingguy-通过在querytanks@EdB的末尾添加提示选项MAXRECURSION 0,您可以轻松绕过最大递归限制。我需要修复max recursion是的,但是max recursion存在是有原因的。如果您的范围不大,那么这可能不是问题。
select distinct (rangestart + n.n) as sequence
from ranges r join
     n
     on r.rangestart + n.n <= r.rangeend
order by sequence;
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
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