如何获取范围内的所有数字

How to get all numbers between a range

我有一个table如下

Id     RFrom      RTo
....  .......    .....
1       10         14
1       22         25
2       100        102
2       176        180

我想获取每个 Id 的每个 RFrom 和 RTo 之间的所有数字。我的预期结果如下

Id     NUMS
....  ......
1       10
1       11
1       12
1       13
1       14
1       22
1       23
1       24
1       25
2       100
2       101
2       102
2       176
2       177
2       178
2       179
2       180

我必须使用游标来实现吗?

这是你的样本table

SELECT * INTO #TEMP FROM
(
    SELECT 1 ID, 10 RFROM, 14 RTO
    UNION ALL
    SELECT 1,       22,         25
    UNION ALL
    SELECT 2,       100,        102
    UNION ALL
    SELECT 2,       176,        180
)TAB

您需要对每个Id使用递归来得到结果

;WITH CTE AS
(
   SELECT ID,RFROM RFROM1,RTO RTO1 
   FROM #TEMP  
   UNION ALL
   SELECT T.ID,RFROM1+1,RTO1 
   FROM #TEMP T
   JOIN CTE ON CTE.ID = T.ID
   WHERE RFROM1 < RTO1
)
SELECT DISTINCT ID,RFROM1 NUMS 
FROM CTE

另一种选择是将 numbers table 与 join 一起使用——递归可能很耗时。

创建数字 table 有多种选择(我建议创建一个永久的),但这里有一个使用通用-table-表达式创建的临时数字:

with numberstable as (
  select top 10000 row_number() over(order by t1.number) as number
  from master..spt_values t1 
      cross join master..spt_values t2
  )
select yt.id,
  nt.number
from yourtable yt
  join numberstable nt on nt.number between yt.rfrom and yt.rto

使用 stacked CTE 创建一个 tally table,与 recursive CTE

相比,它具有更好的性能
declare @min int
select @min= min(RFrom) from yourtable
;WITH e1(n) AS
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), -- 10
e2(n) AS (SELECT 1 FROM e1 CROSS JOIN e1 AS b), -- 10*10
e3(n) AS (SELECT 1 FROM e1 CROSS JOIN e2) -- 10*100
SELECT b.id,
       a.n
FROM   yourtable b
       JOIN (SELECT n = Row_number()OVER (ORDER BY n)+ @min-1
             FROM   e3)a
         ON a.n BETWEEN b.RFrom AND b.RTo
ORDER  BY n; 

检查 here 了解信息