Как проверить, лежит ли месяц и год между двумя датами

У меня есть 2 столбца в таблице startdate и enddate, и мне нужно создать функцию для получения всех ID, которые лежат между данными даты, переданными в функцию. входные параметры моей функции

@Year int,
@Month int = null,
@Quarter int = null

теперь, если месяц равен null, мне нужно проверить только дату, что легко, но если указан месяц, как проверить, находится ли он между startdate и enddate, или же, если указан @Quarter, мне нужно проверить, не совпадают ли 3 месяца года с startdate и enddate .

То, что я написал до сих пор,

CREATE FUNCTION GetAssociatesEmpID(
    @Year int,
    @Month int = null,
    @Quarter int = null
)
RETURNS TABLE
AS BEGIN
IF @Month IS NOT NULL -- Monthly Statistics
    BEGIN

    END
ELSE IF @Quarter IS NOT NULL -- Quarterly Statistics
    BEGIN

    END
ELSE -- Yearly Statistics
    BEGIN
        return SELECT ID FROM Table WHRER @Year>=YEAR(startdate) AND @Year<=YEAR(enddate)
    END
END

Пожалуйста, помогите мне с условием с месяцем и кварталом

Квартал имеет 4 возможных диапазона входных значений от 1 до 4, а диапазон месяцев от @Quarter*3-3 до @Quarter*3.


person user3452098    schedule 24.08.2016    source источник
comment
YEAR(@Year) не имеет смысла, @Year уже INT   -  person Lamak    schedule 24.08.2016
comment
@Lamak о боже, спасибо за указание   -  person user3452098    schedule 24.08.2016
comment
Является ли январь 2016 года периодом между 30 января 2016 года и 02 февраля 2016 года?   -  person Mike Sherrill 'Cat Recall'    schedule 24.08.2016
comment
@MikeSherrill'CatRecall' да, это так   -  person user3452098    schedule 24.08.2016
comment
Похоже, вы просто хотите проверить, перекрываются ли два интервала. Первый интервал находится между startdate и enddate. Второй интервал определяется параметрами процедуры. Преобразуйте ваши параметры @Year, @Month, @Quarter в две правильные даты, используя несколько IFs, а затем проверьте наложение.   -  person Vladimir Baranov    schedule 24.08.2016
comment
Почему бы не передать тип данных даты вместо того, чтобы разбивать его на все эти дополнительные переменные? И тогда вы можете сделать это sargable вместо того, чтобы оборачивать свои столбцы в функции даты, что предотвращает любое использование индекса.   -  person Sean Lange    schedule 24.08.2016


Ответы (2)


Не где я могу проверить, но это должно быть близко...

WHERE 
    (@Year >= YEAR(startdate)) 
    AND 
    (@Year <= YEAR(startdate)) 
    AND 
    (
        ( (@Month IS NOT NULL) AND (@Month >= MONTH(startdate)) AND (@Month <= MONTH(startdate)) )
        OR 
        ( (@Month IS NULL) AND (@Quarter >= DATEPART(QUARTER, startdate)) AND (@Quarter <= DATEPART(QUARTER, startdate)) )
    )
person dazedandconfused    schedule 24.08.2016

Начните с создания двух локальных переменных DateTime. (Или DateTime2, или любой другой тип данных, который используют столбцы дат начала и окончания вашей таблицы.) Возможно, назовите их @WhereStartDate и @WhereEndDate.

Используйте некоторые операторы IF для заполнения ваших новых переменных @WherexxxDate. Например, если указан месяц, что-то вроде:

DECLARE @Year int = 2016;
DECLARE @Month int = 3;
DECLARE @WhereStartDate datetime;
DECLARE @WhereEndDate datetime;

SET @WhereStartDate = CONVERT( datetime, CAST(@Year as char(4)) + '/' + CAST(@Month as varchar(2)) + '/01');
SET @WhereEndDate = DATEADD( day, -1, DATEADD( month, 1, @WhereStartDate ));

SELECT @WhereStartDate, @WhereEndDate;

Когда у вас есть фактические переменные даты/времени, вы можете написать свой запрос соответствующим образом...

SELECT ...
...
WHERE startDate >= @WhereStartDate
AND   enddate <= @WhereEndDate

Это имеет дополнительное преимущество в том, что его можно анализировать. То, как вы написали свой запрос, не подлежит анализу. (Короче говоря, запросы без sargable не будут правильно использовать индексы и будут иметь низкую производительность. Если таблица большая, итоговое сканирование таблицы может занять очень много времени.)

person DeadZone    schedule 24.08.2016