Выделить функцию COALESCE?
У меня большой запрос (не написан мной, но я делаю некоторые изменения). Меня беспокоит то, что у меня одна и та же функция COALESCE примерно в четырех местах. Есть ли способ выделить это, возможно, с помощью выбора из DUAL? Есть ли какой-то выигрыш в производительности?
Вот запрос, слегка озадаченный:
select
tbl1.gid
[snip]
,COALESCE(t1_end_dt, t6_actl_end_dt,t6_calc_end_dt) perd_end_dt
,t1_end_dt
FROM tbl1
....
JOIN tbl2 ON (t2_pk = wpck_wrkr_id AND
t2_ind_1 ='Y' AND
COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt)
BETWEEN t2_strt_dt AND t2_end_dt)
JOIN tbl3 ON (t3_pk = t2_fk_t3_pk AND
COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt)
BETWEEN t3_strt_dt AND t3_end_dt)
LEFT JOIN tbl4 tbl4_a ON (tbl4_a.t4_pk = chkw_wkt_id)
.....
GROUP BY tbl1.gid
.....
,COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt)
,COALESCE(tbl4_b.t4_or_id, tbl4_a.t4_or_id, t7_or_id )
,t1_end_dt
ORDER BY perd_end_dt
Обратите внимание, что я уже разобрал один из COALESCE, назвав его pred_end_dt в SELECT, а затем сослался на него под этим именем в ORDER BY.
4 ответа
Вы должны иметь возможность заменить вхождение в предложении GROUP BY на псевдоним вашего столбца. perd_end_dt
, Но вхождения в условиях JOIN не могут использовать псевдоним столбца.
Это влияет на производительность. Я не думаю, что условия JOIN могут использовать индекс так, как они написаны в настоящее время. Тем не менее, это только один термин в условии JOIN, поэтому влияние может быть очень незначительным. То есть условия, включающие t2_pk
а также t2_ind_1
может уже уменьшить набор строк, поэтому сравнение дат имеет дело только с небольшим набором. Это зависит от того, сколько строк мы говорим и как распределяются данные.
Один из способов выделить COALESCE()
и использование индексации должно было бы создать избыточный столбец, который является результатом этого выражения. Используйте триггеры, чтобы убедиться, что оно имеет правильное значение после каждой вставки или обновления. Затем индексируйте столбец.
Но, как я уже сказал, это может быть больше проблем, чем стоит. Это было бы больше работы, и вы должны быть уверены, что это изменение сделает код более понятным, более корректным или более быстрым.
Другим вариантом будет определение псевдонима для COALESCE()
выражение в подзапросе. Я не могу сказать, из каких таблиц происходят столбцы, потому что вы не квалифицируете их как псевдонимы таблиц. Но если я могу предположить, что они все столбцы tbl1
:
...
FROM (
SELECT COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) perd_end_dt,
t1_fk_t2_pk
FROM tbl1) t1
JOIN tbl2
ON (tbl2.t2_pk = t1.t1_fk_t2_pk AND tbl2.t2_ind_1 = 'Y'
AND t1.perd_end_dt BETWEEN tbl2.t2_strt_dt AND tbl2.t2_end_dt)
...
Есть ли у Oracle взгляды? (Это должно быть.) Если вы обнаружите, что используете это COALESCE()
выражения во многих разных местах, возможно, стоит создать VIEW
и используя это вместо оригинальных таблиц. Ниже будут выполнены те же вычисления, но синтаксис ваших запросов будет более кратким и, следовательно, более понятным.
На мой взгляд, "представление" - это "таблица" в базе данных, а "функция" - "строка кода" в программе. Всякий раз, когда вы находите группу запросов, использующих похожую логику, напишите представление, которое разделяет общую логику, и используйте его вместо этого.
Вы можете создать виртуальную таблицу
(Select Coalesce( all your stuff ....) perdEndDt
From [all your tables necessary for this one value])
и включите эту отдельную объединенную таблицу в ваш Select SQL
Select [all yr other stuff,
Z.perdEndDt
From [Other Tables Joined together]
Join
(Select Coalesce( all your stuff ....) perdEndDt,
[other columns necessary for join conditions]
From [all your tables necessary for this one value]) As Z
On [Join conditions for Z to other tables]
Where [any filter predicates]
Order By Z.perdEndDt
... etc.
Может быть, вы можете использовать с предложением?
with data as
(
select COALESCE(t1_end_dt, t6_actl_end_dt,t6_calc_end_dt) perd_end_dt
, .....
, ...
from tbl1
)
select ...
from data
, ....
where ....