Sql 根据范围拆分记录

Sql 根据范围拆分记录,sql,sql-server,gaps-and-islands,Sql,Sql Server,Gaps And Islands,我有两个表项目和项目范围。在项目表中,所有项目都存在于范围内,即(从和到)编号。我必须从ItemRange表中排除这些数字,即(50到60和70到80) 预期结果: 第一行1到49中的结果,因为50-60在表项范围内……然后在第二行61到69中,因为70-80在表项范围内。。然后81到500,然后600到800与table itemrange相同,因为table itemrange中不存在范围行。如果在结果中的table itemrange中找到任何行,则应将其拆分为2条记录…请任何人帮助我这

我有两个表项目和项目范围。在项目表中,所有项目都存在于范围内,即(从和到)编号。我必须从ItemRange表中排除这些数字,即(50到60和70到80)

预期结果:


第一行1到49中的结果,因为50-60在表项范围内……然后在第二行61到69中,因为70-80在表项范围内。。然后81到500,然后600到800与table itemrange相同,因为table itemrange中不存在范围行。如果在结果中的table itemrange中找到任何行,则应将其拆分为2条记录…请任何人帮助我这是一个孤岛和间隙问题

您可以尝试使用两个
cte
recursive,然后执行
except

最后使用
Row_number
window函数获取间隙编号,然后按其分组

MS SQL Server 2017架构设置

CREATE  table Item
(
    Id int primary key, 
    ItemId int,
    [FROM] int,
    [To] int
)

CREATE table ItemRange
(
    Id int primary key, 
    ItemId int,
    [FROM] int,
    [To] int
)

INSERT INTO Item 
VALUES  
(1,1,1,100),
(2,1,101,500),
(3,1,600,700)

INSERT INTO ItemRange 
VALUES  
(1,1,50,60),
(2,1,70,80)
;WITH CTE AS (
  SELECT ItemId,[FROM],[TO]
  FROM Item
  UNION ALL
  SELECT ItemId,[FROM]+ 1,[TO]
  FROM CTE
  WHERE [FROM]+ 1 <= [TO]
), CTE2 AS(
  SELECT ItemId,[FROM],[TO]
  FROM ItemRange
  UNION ALL
  SELECT  ItemId,[FROM]+ 1,[TO]
  FROM CTE2
  WHERE [FROM]+ 1 <= [TO]
),CTE3 AS(
  SELECT ItemId,[FROM]
  FROM CTE
  except
  SELECT ItemId,[FROM]
  FROM CTE2
)
SELECT ItemId,
       MIN([FROM]) 'FROM',
       MAX([FROM]) 'TO'
FROM (
  SELECT ItemId,[FROM],[FROM] - ROW_NUMBER() OVER(ORDER BY [FROM]) grp
  FROM CTE3
) t1
GROUP BY grp,ItemId
option (maxrecursion 0)
| ItemId | FROM |  TO |
|--------|------|-----|
|      1 |    1 |  49 |
|      1 |   61 |  69 |
|      1 |   81 | 500 |
|      1 |  600 | 700 |
查询1

CREATE  table Item
(
    Id int primary key, 
    ItemId int,
    [FROM] int,
    [To] int
)

CREATE table ItemRange
(
    Id int primary key, 
    ItemId int,
    [FROM] int,
    [To] int
)

INSERT INTO Item 
VALUES  
(1,1,1,100),
(2,1,101,500),
(3,1,600,700)

INSERT INTO ItemRange 
VALUES  
(1,1,50,60),
(2,1,70,80)
;WITH CTE AS (
  SELECT ItemId,[FROM],[TO]
  FROM Item
  UNION ALL
  SELECT ItemId,[FROM]+ 1,[TO]
  FROM CTE
  WHERE [FROM]+ 1 <= [TO]
), CTE2 AS(
  SELECT ItemId,[FROM],[TO]
  FROM ItemRange
  UNION ALL
  SELECT  ItemId,[FROM]+ 1,[TO]
  FROM CTE2
  WHERE [FROM]+ 1 <= [TO]
),CTE3 AS(
  SELECT ItemId,[FROM]
  FROM CTE
  except
  SELECT ItemId,[FROM]
  FROM CTE2
)
SELECT ItemId,
       MIN([FROM]) 'FROM',
       MAX([FROM]) 'TO'
FROM (
  SELECT ItemId,[FROM],[FROM] - ROW_NUMBER() OVER(ORDER BY [FROM]) grp
  FROM CTE3
) t1
GROUP BY grp,ItemId
option (maxrecursion 0)
| ItemId | FROM |  TO |
|--------|------|-----|
|      1 |    1 |  49 |
|      1 |   61 |  69 |
|      1 |   81 | 500 |
|      1 |  600 | 700 |

如何排除?这里的条件是什么?如果@itemRange表中存在任何范围,即50到60和70-80。请检查结果:1到49和61-69,这意味着不包括50到60。。70到80都一样好吧,我想你不明白我的意思,所以请回答这个问题:从哪里49,61,69。。来自?49是ItemRange(50)减去1。。。等等——就我而言understood@EstebanP. 是的,非常感谢@D-Shih…我提供了虚拟数据。实际上,从和到的数字的b/w差异是1000万。这不是我的解决方案。你能给我提供其他解决方案吗。。