Разделение записей на основе диапазона - PullRequest
3 голосов
/ 27 марта 2019

У меня есть 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 находится в элементе таблицы... затем во 2-й строке с 61 по 69, потому что 70-80 в диапазоне элементов таблицы .. затем с 81 по 500, затем 600-800 так же, как и диапазон элементов таблицы, потому что в диапазоне элементов таблицы нет строки диапазона ... если какая-либо строка находится в таблицеitemrange в результате он должен разделиться на 2 записи ... Пожалуйста, помогите мне

1 Ответ

2 голосов
/ 27 марта 2019

Это проблема островов и пробелов.

Вы можете попробовать использовать две 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 |
...