Фильтрация записей из набора данных postgres(greenplum) по значению поля
Существует запрос возвращающий набор справочных данных. Для добавления описания поля depo_rem мы соединяем набор данных с справочником ref_stanh__som_df1d__t. В некоторых случаях, в справочнике есть строки дубликаты, из которых надо выбрать только ту строку(описание поля depoh2.snames AS depo_rem_name), где поле gr = 31.
Для демонстрации проблемы, написал запрос с таким случаем:
SELECT
rcom_14b_t.extract_dttm,
rcom_14b_t.extract_guid,
rcom_14b_t.sec_mod,
sertps.fname AS sec_mod_name,
rcom_14b_t.sec_num,
rcom_14b_t.sec_code,
rcom_14b_t.depo_sec,
depoh1.snames AS depo_sec_name,
rcom_14b_t.id,
rcom_14b_t.iskl,
rcom_14b_t.pr_nep_ep,
rcom_14b_t.depo_rem,
depoh2.snames AS depo_rem_name,
depoh2.gr,
rcom_14b_t.strr,
rcom_14b_t.dt_0,
rcom_14b_t.dt_1,
rcom_14b_t.station_1,
stanh1.fname AS station_1_name,
rcom_14b_t.fuel_1,
rcom_14b_t.dt_2,
rcom_14b_t.station_2,
stanh2.fname AS station_2_name,
rcom_14b_t.fuel_2,
rcom_14b_t.otchmonth,
rcom_14b_t.otchyear,
rcom_14b_t.otchdor,
rr.sname AS otchdor_name
FROM hes.rcom_14b__som_df1d__t rcom_14b_t
LEFT JOIN hes.ref_dor__som_df1d__t rr ON rcom_14b_t.otchdor = rr.code
LEFT JOIN hes.ref_sertps__som_df1d__t sertps ON rcom_14b_t.sec_mod = sertps.code AND date(rcom_14b_t.dt_0) >= sertps.dtbegd AND date(rcom_14b_t.dt_1) <= sertps.dtendd
LEFT JOIN hes.ref_depoh__som_df1d__t depoh1 ON rcom_14b_t.depo_sec = depoh1.code AND date(rcom_14b_t.dt_0) >= depoh1.dtbegs AND date(rcom_14b_t.dt_0) <= depoh1.dtends
left join hes.ref_depoh__som_df1d__t as depoh2 on rcom_14b_t.depo_rem = depoh2.code AND ( rcom_14b_t.dt_0 >= depoh2.dtbegs AND rcom_14b_t.dt_0 <= depoh2.dtends )
LEFT JOIN hes.ref_stanh__som_df1d__t stanh1 ON rcom_14b_t.station_1 = stanh1.code6 AND date(rcom_14b_t.dt_0) >= stanh1.dtbegs AND date(rcom_14b_t.dt_0) <= stanh1.dtends
LEFT JOIN hes.ref_stanh__som_df1d__t stanh2 ON rcom_14b_t.station_2 = stanh2.code6 AND date(rcom_14b_t.dt_0) >= stanh2.dtbegs AND date(rcom_14b_t.dt_0) <= stanh2.dtends
where rcom_14b_t.sec_mod = 625 and depo_sec = 112 and fuel_2 = 1632;
Имеющееся решение имеет проблемы производительности:
SELECT rcom_14b_t.extract_dttm,
rcom_14b_t.extract_guid,
rcom_14b_t.sec_mod,
sertps.fname AS sec_mod_name,
rcom_14b_t.sec_num,
rcom_14b_t.sec_code,
rcom_14b_t.depo_sec,
depoh1.snames AS depo_sec_name,
rcom_14b_t.id,
rcom_14b_t.iskl,
rcom_14b_t.pr_nep_ep,
rcom_14b_t.depo_rem,
depoh2.snames AS depo_rem_name,
rcom_14b_t.strr,
rcom_14b_t.dt_0,
rcom_14b_t.dt_1,
rcom_14b_t.station_1,
stanh1.fname AS station_1_name,
rcom_14b_t.fuel_1,
rcom_14b_t.dt_2,
rcom_14b_t.station_2,
stanh2.fname AS station_2_name,
rcom_14b_t.fuel_2,
rcom_14b_t.otchmonth,
rcom_14b_t.otchyear,
rcom_14b_t.otchdor,
rr.sname AS otchdor_name
FROM hes.rcom_14b__som_df1d__t rcom_14b_t
LEFT JOIN hes.ref_dor__som_df1d__t rr ON rcom_14b_t.otchdor = rr.code
LEFT JOIN hes.ref_sertps__som_df1d__t sertps ON rcom_14b_t.sec_mod = sertps.code AND date(rcom_14b_t.dt_0) >= sertps.dtbegd AND date(rcom_14b_t.dt_1) <= sertps.dtendd
LEFT JOIN hes.ref_depoh__som_df1d__t depoh1 ON rcom_14b_t.depo_sec = depoh1.code AND date(rcom_14b_t.dt_0) >= depoh1.dtbegs AND date(rcom_14b_t.dt_0) <= depoh1.dtends
LEFT JOIN LATERAL ( SELECT depoh2_1.snames
FROM hes.ref_depoh__som_df1d__t depoh2_1
WHERE rcom_14b_t.depo_rem = depoh2_1.code AND rcom_14b_t.dt_0 >= depoh2_1.dtbegs AND rcom_14b_t.dt_0 <= depoh2_1.dtends
ORDER BY
CASE depoh2_1.gr
WHEN 31 THEN 1
ELSE 2
END
LIMIT 1) depoh2 ON 1 = 1
LEFT JOIN hes.ref_stanh__som_df1d__t stanh1 ON rcom_14b_t.station_1 = stanh1.code6 AND date(rcom_14b_t.dt_0) >= stanh1.dtbegs AND date(rcom_14b_t.dt_0) <= stanh1.dtends
LEFT JOIN hes.ref_stanh__som_df1d__t stanh2 ON rcom_14b_t.station_2 = stanh2.code6 AND date(rcom_14b_t.dt_0) >= stanh2.dtbegs AND date(rcom_14b_t.dt_0) <= stanh2.dtends;
Как решить эту задачу оптимальнее?
Использую: PostgreSQL 9.4.26 (Greenplum Database 6.21.3 build commit:622fa9a831d189db93b0e2c348f1379d7d5f6e9d Open Source) on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 6.4.0, 64-bit compiled on Oct 27 2022 17:36:45