Для начала я представлю свою первую проблему, которую я решил, а затем объясню дополнительные условия, добавленные в уравнение.
У меня есть таблица с уникальным индексом контрактов клиентов, которые живут в домах, и я хочу знать, сколько дней требуется, чтобы дом заселился следующим человеком. Мы также создаем «пустые» контракты в то время, когда дом пуст, поэтому мы можем рассчитать, что $$ мы пропустили, выбрав «пустые» контракты.
Это работает так:
AGREEMENTTYPE = 0 означает жилой
AGREEMENTTYPE = 3 означает пусто
Теперь я хочу узнать, сколько дней требуется, чтобы дом (RENTALOBJECTID) снова заселился после того, как кто-то вышел. Так, например:
RENTALOBJECTID 1, CONTRACTID HC001, AGREEMENTTYPE 0, ended 3/1/2019
RENTALOBJECTID 1, CONTRACTID HC002, AGREEMENTTYPE 3, starts 3/1/2019, ends 6/1/2019 (the empty contract in between).
RENTALOBJECTID 1, CONTRACTID HC003, AGREEMENTTYPE 0, starts 6/1/2019
Общее время между HC001 и HC003 составляет 3 месяца.
У меня есть запрос, который уже отлично вычисляет это, но теперь он начинает становиться интересным. Сначала я покажу вам, что у меня есть:
WITH PMC
AS (SELECT CONTRACTID,
RENTALOBJECTID,
AGREEMENTTYPE,
VALIDFROM,
VALIDTO,
ConcatResult = MIN(CASE
WHEN AGREEMENTTYPE <> 0
THEN FORMAT(VALIDFROM, 'yyyy-MM-dd')
+ FORMAT(ISNULL(VALIDTO, '1900-01-01'), 'yyyy-MM-dd')
+ CONTRACTID
END)
OVER (
PARTITION BY RENTALOBJECTID
ORDER BY VALIDFROM DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
FROM PMCCONTRACT)
SELECT *,
NextContractId = SUBSTRING(ConcatResult, 21, 10),
NextValidFrom = CAST(SUBSTRING(ConcatResult, 1, 10) AS DATE),
NextValidTo = CAST(NULLIF(SUBSTRING(ConcatResult, 11, 10), '1900-01-01') AS DATE)
FROM PMC
ORDER BY RENTALOBJECTID,
VALIDFROM
Что приводит к следующим данным:
CONTRACTID RENTALOBJECTID AGREEMENTTYPE STATECODE VALIDFROM VALIDTO NextContractID NextValidFrom NextValidTo
HC001 1 3 NULL 1/1/2015 3/1/2019 HC004 6/1/2019 NULL
HC002 1 0 2 3/1/2019 4/1/2019 NULL NULL NULL
HC003 1 0 1 4/1/2019 6/1/2019 NULL NULL NULL
HC004 1 3 NULL 6/1/2019 NULL NULL NULL NULL
Тем не менее, в некоторых случаях между AND имеется несколько контрактов RE AGREEMENTTYPE = 3 ’, которые относятся к определенному типу, который вы не хотите включать во время выполнения заказа. Мы называем это «STATECODE». Контракты с AGREEMENTTYPE = 3, с STATECODE = 2, которые мы не хотим включать в расчет времени выполнения заказа в днях.
Следующий пример показывает, что я имею в виду:
RENTALOBJECTID 1, CONTRACTID HC001, AGREEMENTTYPE 0, STATECODE NULL, ended 3/1/2019
RENTALOBJECTID 1, CONTRACTID HC002, AGREEMENTTYPE 3, STATECODE 2, starts 3/1/2019, ends 4/1/2019 (the empty contract in between)
RENTALOBJECTID 1, CONTRACTID HC003, AGREEMENTTYPE 3, STATECODE 1, starts 4/1/2019, ends 6/1/2019
RENTALOBJECTID 1, CONTRACTID HC004, AGREEMENTTYPE 0, STATECODE NULL, starts 6/1/2019
Время между контрактом HC001 и HC004 составляет 3 месяца, затем -1 месяц контракта HC002, который мы должны опустить = в общей сложности 2 месяца.
Возможно, у вас есть лучшее предложение, но сейчас я хочу, чтобы данные выглядели следующим образом, поскольку тогда я могу легко рассчитать время выполнения заказа в днях между контрактами для определенного RENTALOBJECTID.
CONTRACTID RENTALOBJECTID AGREEMENTTYPE STATECODE VALIDFROM VALIDTO NextContractID NextValidFrom NextValidTo NextStatecode2Contract NextStatecode2ValidFrom NextStatecode2ValidTo
HC001 1 3 NULL 1/1/2015 3/1/2019 HC004 6/1/2019 NULL HC002 3/1/2019 4/1/2019
HC002 1 0 2 3/1/2019 4/1/2019 NULL NULL NULL NULL NULL NULL
HC003 1 0 1 4/1/2019 6/1/2019 NULL NULL NULL NULL NULL NULL
HC004 1 3 NULL 6/1/2019 NULL NULL NULL NULL NULL NULL NULL
Итак, в основном я хочу рассчитать время между КОНТРАКТАМИ с AGREEMENTTYPE 0, минус период КОНТРАКТОВ с AGREEMENTTYPE 3 и STATECODE 2. Но так как это используется в качестве измерения для моей модели данных, это причина, почему я хочу включите эти последние три как вычисленные столбцы. Столбец должен быть рассчитан где-то по линиям:
NextStatecode2Contract:
IF CONTRACT has AGREEMENTTYPE 3 and IF one of the next contracts has a CONTRACT with AGREEMENTTYPE 0
AND STATECODE 2 BEFORE the Next Contract with AGREEMENTTYPE 3,
THEN SELECT THE NEXT CONTRACT OF AGREEMENTTYPE 0 AND STATECODE 2.
NextStatecode2ValidFrom:
IF CONTRACT has AGREEMENTTYPE 3 and IF one of the next contracts has a CONTRACT with AGREEMENTTYPE 0
AND STATECODE 2 BEFORE the Next Contract with AGREEMENTTYPE 3,
THEN SELECT VALIDFROM OF THE NEXT CONTRACT OF AGREEMENTTYPE 0 AND STATECODE 2.
NextStatecode2ValidTo
IF CONTRACT has AGREEMENTTYPE 3 and IF one of the next contracts has a CONTRACT with AGREEMENTTYPE 0
AND STATECODE 2 BEFORE the Next Contract with AGREEMENTTYPE 3,
THEN SELECT VALIDTO OF THE NEXT CONTRACT OF AGREEMENTTYPE 0 AND STATECODE 2.