我有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,因为表项范围是70-80。然后81到500然后600-800相同表itemrange,因为表itemrange中不存在范围行。.如果结果在表itemrange中找到任何行,则应拆分为2条记录...请有人帮助我
答案 0 :(得分: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)
Results :
| ItemId | FROM | TO |
|--------|------|-----|
| 1 | 1 | 49 |
| 1 | 61 | 69 |
| 1 | 81 | 500 |
| 1 | 600 | 700 |