Работа с периодами пересечения диапазонов дат - PullRequest
1 голос
/ 17 июня 2019

У меня есть таблица с диапазоном дат, указанным в полях DateFrom и DateTo, и полем TotalValue.

В зависимости от указанного диапазона дат, т. Е. Это:

DECLARE @ReportStartDate datetime = '31 May 2019'
DECLARE @ReportEndDate datetime = '2 Jun 2019'

Он будет принимать значения NULL, а также строку 2019-05-31-2019-06-07, но значение TotalValue будет (48/7) * 2, поскольку это только 2 дня диапазона.

Ожидаемый результат.

enter image description here

Если указано ниже:

DECLARE @ReportStartDate datetime = '04 Jun 2019'
DECLARE @ReportEndDate datetime = '14 Jun 2019'

Он будет принимать значения NULL, а также строку 2019-05-31-2019-06-05, но значение TotalValue будет (48/7) * 3, поскольку это всего 3 дня диапазона.

Ожидаемый результат

enter image description here

Кто-нибудь знает, как к этому можно подойти? У меня есть следующий запрос, который решает вариант использования 1, но я не уверен, как подходить к варианту использования 2

select 
    *,
    CASE WHEN DateFrom is null Then TotalValue Else (TotalValue/7) * DateDiff(dd,DateFrom,@ReportEndDate) END as CalculatedValue
from 
    #TestData
where DateFrom is null
or DateFrom >=@ReportStartDate

Пример данных

CREATE TABLE #TestData
(
    DateFrom date NULL,
    DateTo date NULL,
    TotalValue money
)
INSERT INTO #TestData
(
    DateFrom,
    DateTo,
    TotalValue
)
SELECT
    NULL,
    NULL,
    250
UNION ALL
SELECT
    '2019-05-31',
    '2019-06-07',
    48
UNION ALL
SELECT
    '2019-05-24',
    '2019-05-31',
    336
UNION ALL
SELECT
    NULL,
    NULL,
    134 
UNION ALL
SELECT
    '2019-04-19',
    '2019-04-26',
    336

select * from #TestData

drop table #TestData

1 Ответ

1 голос
/ 17 июня 2019

Используйте выражение case, datediff и пару iif, чтобы получить CalculatedValue.

. Выражение case имеет две ветви:

  1. Если столбец DateFrom или DateTo имеет null вместо value, вы просто возвращаете TotalValue.

  2. Вот где это становится интересным: если диапазоны дат перекрываются, подсчитайте количество дней, в которое они перекрываются, а затем разделите TotalValue на 7 и умножьте его на количество дней..

Я добавил несколько комментариев к коду, надеюсь, он достаточно понятен:

DECLARE @ReportStartDate date = '2019-05-31', @ReportEndDate date = '2019-06-02'

SELECT  DateFrom, 
        DateTo, 
        TotalValue,
        CASE 
            -- dates are null
            WHEN DateFrom IS NULL OR DateTo IS NULL THEN TotalValue

            -- devide by 7 and multiply be the number of days within range
            ELSE TotalValue / 7 * DATEDIFF(DAY,
                                           -- latest of start dates
                                           IIF(DateFrom > @ReportStartDate, DateFrom, @ReportStartDate),
                                           -- earliest of end dates
                                           IIF(DateTo < @ReportEndDate, DateTo, @ReportEndDate)
                                           )
        END  As CalculatedValue
FROM #TestData
-- Get only date ranges that overlap or the date columns are null
WHERE (DateFrom IS NULL OR DateFrom < @ReportEndDate)
AND (DateTo IS NULL OR DateTo > @ReportStartDate)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...