Использование trunc()
для значения столбца предотвратит использование индекса для этого столбца (если это не индекс на основе функций). Лучше использовать диапазон дат, охватывающий весь интересующий вас день. Добавление временного смещения к start_date
также повлияет на индекс; и '10-Feb-2020'
- это строка, а не дата, так что вы выполняете неявное преобразование - никогда не бывает хорошей идеей. Вам также не нужно distinct
с union
как (в отличие от union all
), который в любом случае устраняет дубликаты.
Я бы предложил что-то вроде этого в качестве отправной точки:
select car_no, start_date
from tab_1
where source_point = end_point
and start_date >= date '2020-02-10' - actual_arrival_time * interval '1' minute
and start_date < date '2020-02-11' - actual_arrival_time * interval '1' minute
union
select car_no, start_date
from tab_2
where event_code='TD'
and actl_time_of_arrvl >= date '2020-02-10'
and actl_time_of_arrvl < date '2020-02-11'
actual_arrival_time * interval '1' minute
дает вам тот же эффект, что и ACTUAL_ARRIVAL_TIME END/1440
; первый тип данных - интервал, второй - доля дня, но оба представляют количество минут как значение, которое может быть добавлено к значению даты.
Я использую литералы даты, которые все еще жестко закодированы. Если вы действительно используете параметр, вы можете добавить interval '1' day
к желаемой дате вместо жесткого кодирования через день. В любом случае, будут искать значения в или после полуночи первой даты и до полуночи второй даты - что охватывает все возможные времена в этот день.
Первая ветвь все еще может ' на самом деле использовать индекс правильно из-за изменчивости ссылки на другое значение столбца в расчете диапазона, но если вы знаете, например, что actual_arrival_time
в течение 24 часов, вы могли бы помочь с этим более жестким ограничением:
select car_no,start_date
from tab_1
where source_point = end_point
and start_date >= date '2020-02-10'
and start_date < date '2020-02-10' + interval '2' day -- depending on allowed ranges
and start_date + actual_arrival_time * interval '1' minute >= date '2020-02-10'
and start_date + actual_arrival_time * interval '1' minute < date '2020-02-10' + interval '1' day
union
select car_no, start_date
from tab_2
where event_code='TD'
and actl_time_of_arrvl >= date '2020-02-10'
and actl_time_of_arrvl < date '2020-02-10' + interval '1' day
Здесь start_date >= date '2020-02-10'
дает индексу нижнюю границу для поиска (при условии, что actual_arrival_time
не может быть отрицательным, что кажется разумным); и start_date < date '2020-02-10' + interval '2' day
дает верхнюю границу. Что это верхняя граница будет зависеть от допустимых значений, особенно для actual_arrival_time
.
В вашем вопросе неясно, является ли tab1.start_date
всегда полночью, поэтому вы можете упростить первую часть проверки к точной дате совпадения вместо диапазона. Но тогда, глядя на actual_arrival_time
, вероятно, не понадобится ... если start_date
на самом деле всегда полночь, а actual_arrival_time
ограничено между 0 и 1440, то это может быть просто:
select car_no,start_date
from tab_1
where source_point = end_point
and start_date >= date '2020-02-10'
and start_date < date '2020-02-10' + interval '1' day
union
...
точно так же как вторая ветка. Но то, как вы пытались приблизиться к нему, говорит о том, что это может быть не так, и вам просто нужно максимально сузить начальный индексный поиск, прежде чем выполнять фильтрацию по точному времени. Я подозреваю, что actual_arrival_time
может представлять несколько дней, или даже недель или месяцев; поэтому, возвращаясь к предыдущей версии,
and start_date < date '2020-02-10' + interval '2' day -- depending on allowed ranges
расширится до максимума, который вы ожидаете увидеть; или, возможно, может быть полностью опущен.
Вам нужно взглянуть на план выполнения, чтобы увидеть, что он на самом деле делает, хотя, вероятно, для общего запроса и каждой ветви объединения отдельно.
Если Вы будете делать это много, возможно, стоит добавить вычисленное значение start_date + actual_arrival_time * interval '1' minute
к tab1
как виртуальный столбец и проиндексировать его.