Проверьте, присутствует ли данный месяц + дата в данных, содержащих диапазон месяца + дата - PullRequest
3 голосов
/ 30 апреля 2011

Вот мой запрос:

DECLARE @MM INT -- Current month
DECLARE @DD INT -- Current date

SET @MM = 1 -- For testing, set it to January
SET @DD = 1 -- For testing, set it to 01

SELECT xxxID, xxxFK, StartMonth, StartDate, StopMonth, StopDate, NULL AS OKorNOT
FROM xxxTable
ORDER BY xxxFK

А вот и данные:

xxxID            xxxFK       StartMonth  StartDate   StopMonth   StopDate    OKorNOT     
---------------- ----------- ----------- ----------- ----------- ----------- ----------- 
8                2287        11          15          1           2           NULL
4                2290        2           1           2           21          NULL
2                2306        9           15          10          31          NULL
3                2306        1           3           1           20          NULL
9                2661        11          15          1           3           NULL
10               2661        5           5           5           31          NULL
5                3778        6           2           9           5           NULL
6                3778        1           1           3           31          NULL
7                3778        5           10          5           31          NULL
1                3778        12          10          12          31          NULL

Мне нужно заполнить столбец OKorNot 1/0 в зависимости от того, находится ли данная дата месяца между StartMonth-StartDate и StopMonth-StopDate. Кстати, это SQL Server 2000.

EDIT

Здесь следует отметить, что в данных не хранятся годы, и даты-месяцы могут начинаться, скажем, 15 ноября и заканчиваться 15 января, поэтому 31 декабря и 1 января этот случай должен верните истину.

Ответы [ 3 ]

2 голосов
/ 30 апреля 2011
SELECT *
FROM xxxTable
WHERE (StartMonth < StopMonth OR StartMonth = StopMonth AND StartDate<=StopDate)
    AND (@MM > StartMonth OR @MM = StartMonth AND @DD >= StartDate)
    AND (@MM < StopMonth OR @MM = StopMonth AND @DD <= StopDate)
    OR (StartMonth > StopMonth OR StartMonth = StopMonth AND StartDate>StopDate)
        AND ((@MM > StartMonth OR @MM = StartMonth AND @DD >= StartDate)
            OR (@MM < StopMonth OR @MM = StopMonth AND @DD <= StopDate))
2 голосов
/ 30 апреля 2011

Использование только целочисленных операций и воображаемого календаря на 384 дня

Поскольку ваши даты представляют собой комбинации месяца и дня, я попытался создать целое число для каждой такой комбинации, целое число, которое является уникальным и также сохраняет порядок. Чтобы сделать вычисления максимально простыми, мы придумали новый календарь, в котором все месяцы имеют ровно 32 дня, и мы действуем так, как будто наши даты взяты из этого календаря. Затем, чтобы узнать, сколько дней прошло с 1 января, мы имеем формулу:

DaysPast = 32 * month + day

(ОК, должно быть 32 * (month-1) + (day-1), но так проще, и мы хотим сравнивать даты только относительно друг друга, а не 1 января. И результат по-прежнему уникален для каждой даты).

Поэтому сначала мы вычисляем DaysPast для нашей контрольной даты:

SET @CHECK = 32 * @MM + @DD

Затем мы вычисляем DaysPast для всех дат (как начальных, так и конечных) в нашей таблице:

  ( SELECT *
         , (32 * StartMonth + StartDate) AS Start
         , (32 * StopMonth  + StopDate ) AS Stop
    FROM xxxTable
  ) AS temp

Тогда у нас есть два случая.

  • Первый случай, когда Start = (8-Feb) и Stop = (23-Nov).

Тогда первое условие @CHECK BETWEEN Start AND Stop будет выполнено, а даты между Start и Stop будут в порядке.

Вторым условием будет Ложь, поэтому больше дат не будет.

  • Второй случай, когда Start = (23-Nov) и Stop = (8-Feb). :

Тогда первое условие @CHECK BETWEEN Start AND Stop будет ложным, потому что Start больше Stop, поэтому никакие даты не могут соответствовать этому условию.

Второе условие Stop < Start будет истинным, поэтому мы также проверяем, если
@CHECK НЕ BETWEEN (9-Feb) AND (22-Nov)
чтобы соответствовать датам до (9-Feb) или после (22-Nov).

DECLARE @CHECK INT
SET @CHECK = 32 * @MM + @DD

SELECT *
     , CASE WHEN
           @CHECK BETWEEN Start AND Stop 
           OR ( Stop < Start 
               AND @CHECK NOT BETWEEN Stop+1 AND Start-1
              )
         THEN 1
         ELSE 0
       END
       AS OKorNOT
FROM 
  ( SELECT *
         , (32 * StartMonth + StartDate) AS Start
         , (32 * StopMonth  + StopDate ) AS Stop
    FROM xxxTable
  ) AS temp
ORDER BY xxxFK
2 голосов
/ 30 апреля 2011

Было бы проще, если бы вы хранили даты как, ну, в общем, даты ...

Во всяком случае, как-то так. Я не проверял. И вам нужно иметь дело с границей года, которую я сделал

SELECT
    xxxID, xxxFK, StartMonth, StartDate, StopMonth, StopDate,
    CASE 
       WHEN
          FullStart <= FullStop AND 
            DATEADD(month, @MM-1, DATEADD(day, @DD-1, 0)) BETWEEN FullStart AND FullStop
                      THEN 1
       WHEN
          FullStart > FullStop AND 
            DATEADD(month, @MM-1, DATEADD(day, @DD-1, 0)) BETWEEN
                    FullStart AND DATEADD(year, 1, FullStop)
                      THEN 1  
       ELSE 0
    END AS OKOrNot
FROM
    (
    SELECT
        xxxID, xxxFK, StartMonth, StartDate, StopMonth, StopDate,
        DATEADD(month, StartMonth-1, DATEADD(day, StartDate-1, 0)) AS FullStart,
        DATEADD(month, StopMonth-1, DATEADD(day, StopDate-1, 0)) AS FullStop
    FROM xxxTable
    ) foo
ORDER BY xxxFK

edit: добавлено «-1» ко всем значениям: если мы уже Ян, не добавляем еще месяц ...

...