«Условные условия» в предложении WHERE (какое условие применяется, зависит от флага «mode») - PullRequest
5 голосов
/ 21 апреля 2009

У меня есть ситуация, которую я решил двумя разными способами, но мне было интересно, что люди думают о вариантах, и есть ли у них какие-либо другие альтернативы ...

Система обрабатывает «интервалы» данных.

  • Все данные распределены на «интервал»
  • Интервал представлен DATETIME "interval_start" в таблице фактов
  • Таблица измерений содержит продолжительность «интервала» (может быть разной для разных сущностей)
  • Также в таблице измерений есть флаг «mode»


Следующие правила необходимы в запросе SQL ...

Режим 0
Если запись записи находится в таблице фактов, она может быть обработана.
(Без ограничений.)

Режим 1
Запись действительна только для обработки, если "interval_start" был в прошлом. (Интервалы времени, которые уже начались, но не обязательно заканчиваются.)

Режим 2
Запись действительна только для обработки, если весь «интервал» был в прошлом. (Интервалы времени, которые закончились.)


Первое предложение WHERE, созданное для этого, было следующим ...

WHERE
    getDate() >=
        CASE [table].mode
            WHEN 0 THEN 0
            WHEN 1 THEN [log].interval_start
            WHEN 2 THEN [log].interval_start + [table].interval_period
            ELSE        NULL
        END


Была обеспокоенность тем, что это может помешать индексам оптимизировать предложение. Альтернативой было использование нескольких условий И / ИЛИ.

WHERE
   ([table].mode = 0 AND getDate() >= 0)
OR ([table].mode = 1 AND getDate() >= [log].interval_start)
OR ([table].mode = 2 AND getDate() >= [log].interval_start + [table].interval_period)


Очевидно, что то, что будет работать лучше всего, будет зависеть от данных, индексов и т. Д. Но есть ли у кого-нибудь мнение или альтернатива тому, что я сейчас называю «условными условиями»? :)

Ура, Mat.

Ответы [ 2 ]

5 голосов
/ 21 апреля 2009

Как насчет:

WHERE
     interval_start <= CASE mode
                         WHEN 0 THEN '9999-12-31'
                         WHEN 1 THEN GETDATE()
                         WHEN 2 THEN GETDATE() - interval_period
                       END
3 голосов
/ 21 апреля 2009

Другой вариант - запустить три отдельных запроса и объединить их вместе. В зависимости от вашего индекса и структуры таблицы это может привести к более эффективному SQL, чем объединение предложений в предложении WHERE или использование операторов CASE, хотя это будет чисто игровой оптимизатор.

Я бы протестировал все три подхода и выбрал тот, который лучше всего подходит для вас.

...