DB2 - SAS сложное состояние - PullRequest
       12

DB2 - SAS сложное состояние

0 голосов
/ 15 ноября 2018

Я пытаюсь улучшить время выполнения моего запроса.

Мне нужно извлечь строки, где последний день месяца находится между начальной и конечной датами.

В моей таблице данные настроены по примеру недели: начало 2018-11-11, конец 2018-11-17, начало 2018-11-18, конец 2018-11-24 и т. Д.

мой запрос выглядиткак это:

select field1, field2,
max(case when '2018-01-31' between start and end then 1 else 0 end) as M1,
max(case when '2018-02-28' between start and end then 1 else 0 end) as M2,
....
max(case when '2018-12-31' between start and end then 1 else 0 end) as M12
from tableX
where start between '2018-01-01' and '2018-12-31'
group by field1, field2

Так что я хочу рассмотреть только те строки, которые включают конец месяцев.Любая идея, как я мог бы улучшить это?

Я думаю сделать что-то подобное в предложении where:

where '2018-01-31' between start and end
or '2018-02-28' between start and end
...
or '2018-12-31' between start and end

Возможно ли сделать что-то вроде этого:

where ('2018-01-31','2018-02-28',....,'2018-12-31') between start and end

Спасибо

Франк

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Принятый ответ минимизирует количество обрабатываемых строк.

where LAST_DAY(start) between start and end

Это, однако, все равно будет обрабатывать строки за пределами года, который вы хотите. Таким образом, вы все равно должны использовать граничные условия. Такие как ...

where LAST_DAY(start) between start and end
  and start between '2018-01-01' and '2018-12-31'

У него все еще есть недостаток: ни один индекс не может удовлетворить условию LAST_DAY(), и произойдет сканирование таблицы или индекса.

С помощью информации, предоставленной вами в комментариях, использование поиска по индексу может быть восстановлено.

Каждая строка всегда на неделю и начинается в понедельник. Таким образом, для каждого конкретного конца месяца, если мы вернемся к понедельнику, мы получим start, который соответствует.

WHERE
    start IN (
        DATE_TRUNC(WEEK, LAST_DAY('2018-01-01')), -- find last day in jan, round down to Monday
        DATE_TRUNC(WEEK, LAST_DAY('2018-02-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-03-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-04-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-05-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-06-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-07-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-08-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-09-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-10-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-11-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-12-01'))
    )

Это значительно дольше.

Это можно уменьшить с помощью таблицы календаря со списком дат и метаданными о тех датах, которые помогут вам выполнять быстрый поиск.

А пока создайте индекс для start и попробуйте явное предложение where выше. Это должно быть даже быстрее, чем вы уже пробовали.


EDIT:

Точно так же вы могли бы написать свои CASE выражения - это способ, который «легче читать человеку» ...

MAX(CASE WHEN start = DATE_TRUNC(WEEK, LAST_DAY('2018-01-01')) THEN 1 ELSE 0 END)   AS M01
0 голосов
/ 15 ноября 2018

В зависимости от версии Db2 и платформы функция LAST_DAY может помочь.Рассмотрим что-то вроде этого:

where LAST_DAY(start) between start and end
...