Вот мой подход к этой проблеме. Я бы использовал таблицу чисел для создания записи для каждой даты в новом диапазоне для каждого идентификатора бронирования. Затем я разделил бы эти данные по идентификатору бронирования, упорядоченному по дате. Выполнение того же лога раздела c для существующих данных позволит должным образом объединить записи.
Затем я бы выполнил операцию DELETE
, а затем операцию INSERT
. Это оставит вас с соответствующим количеством записей. Единственное, что нужно сделать вручную, - это заполнить вспомогательные данные для резервирований расширенными диапазонами дат. Я расширил один из ваших новых диапазонов, чтобы показать этот сценарий.
Я отметил, где установка для этой демонстрации заканчивается в коде ниже. Все, что ниже, - это мое решение, которое должно быть реализовано с вашими реальными таблицами.
--Ranges Table
DECLARE @ranges TABLE
(
ID INT
,StartDate DATETIME
,EndDate DATETIME
)
DECLARE @t1 TABLE
(
ResaID INT
,StayDate DATETIME
,ColA INT
,ColB NVARCHAR(100)
,ColC BIT
)
INSERT INTO @t1
(
ResaID
,StayDate
,ColA
,ColB
,ColC
)
VALUES
(100, '2020-02-03', 1, 'A', 0)
,(100, '2020-02-04', 100, 'B', 1)
,(100, '2020-02-05', 255, 'C', 1)
,(120, '2020-04-06', 34, 'D', 1)
,(120, '2020-04-07', 67, 'E', 0)
,(120, '2020-04-08', 87, 'F', 0)
,(120, '2020-04-09', 545, 'G', 1)
,(120, '2020-04-10', 288, 'H', 0)
INSERT INTO @ranges
(
ID
,StartDate
,EndDate
)
VALUES
(100, '2020-06-04', '2020-06-07')
,(120, '2021-03-01', '2021-03-05')
--END DEMO SETUP
DROP TABLE IF EXISTS #numbers
DROP TABLE IF EXISTS #newRecords
--GENERATE NUMBERS TABLE
;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 e2 CROSS JOIN e2 AS b), -- 100*100
e4(n) AS (SELECT 1 FROM e3 CROSS JOIN (SELECT TOP 5 n FROM e1) AS b) -- 5*10000
SELECT ROW_NUMBER() OVER (ORDER BY n) as Num
INTO #numbers
FROM e4
ORDER BY n;
;with oldData --PARTITION THE EXISTING RECORDS
AS
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY ResaID ORDER BY STAYDATE) as ResPartID
FROM @t1
)
,newRanges --GENERATE YOUR NEW RANGES AND PARITITION
AS
(
select
r.ID
,CAST(n.num as DATETIME) as StayDate
,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY n.num) as ResPartID
from @ranges r
inner join #numbers n on CAST(r.StartDate as INT) <= n.Num AND CAST(r.EndDate as INT) >= n.Num
)
SELECT n.ID
,n.StayDate
,o.ColA
,o.ColB
,o.ColC
into #newRecords
FROM newRanges n
left join oldData o on n.ID = o.ResaID and n.ResPartID = o.ResPartID
--DELETE OLD RECORDS
DELETE t
FROM @t1 t
inner join @ranges r on t.ResaID = r.ID
--INSERT NEW DATA
INSERT INTO @t1
(
ResaID
,StayDate
,ColA
,ColB
,ColC
)
SELECT
ID
,StayDate
,ColA
,ColB
,ColC
FROM #newRecords
SELECT * FROM @t1