sql - 根据范围拆分记录
问题描述
我有 2 个表项目和项目范围。在项目表中,所有项目都存在于范围内,即(从和到)数字。我必须从 ItemRange 表中排除这些数字,即(50 到 60 和 70 到 80)。
Declare @Item table
(
Id int primary key,
ItemId int,
[FROM] int,
[To] int
)
Declare @ItemRange table
(
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)
预期结果:
结果在第一行 1 到 49 因为 50-60 在表 itemrange 中......然后在第二行 61 到 69 因为表 itemrange 中的 70-80 .. 然后 81 到 500 然后 600-800 与表 itemrange 相同,因为表itemrange中不存在范围行..如果在结果中的表itemrange中找到任何行,它应该拆分为2条记录...请任何人帮助我
解决方案
这是一个孤岛和差距问题。
您可以尝试使用两个cte
递归然后执行except
。
最终使用Row_number
窗口函数得到间隙数,然后按它分组。
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)
查询 1:
;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 |
推荐阅读
- java - 堆中对象的内存引用是否会耗尽空间?
- excel - Excel。日期和时间 = 轮班 X
- c# - 外部表外键值始终显示 null ef core 3.1
- r - 为什么我不能在 Rstudio 中为我的条形图添加颜色?
- azure - 使用 MSDeploy 将 Web 应用程序部署到 Azure 应用服务
- c++ - 如何在 C++ 中将链表的起始指针作为指针传递
- c++ - 无法在 Visual Studio 2019 中选择 C++ 语言标准
- java - jaxb2:xjc 两个声明导致 ObjectFactory 类中的冲突。在 XSD 中使用类型扩展时
- user-interface - Blender - 使用 bpy 插入文本按钮
- tensorflow - 一维信号阵列上的异步损失函数