请让我知道如何优化此查询以提高性能/执行时间。
PS-它是由另一个人开发并移交给我的。
查询已附加(我知道这是一个很大的查询!)-
任何有关如何使用aggregrates处理联接和子查询的想法都会很有帮助。
SELECT /*+MONITOR*/ gcibjdnf.danfe,
gcibjdnf.bjd_situacao,
gcibjdnf.obs_rejeicao,
gcibjdnf.bjd_tipo_cobranca,
gcibjdnf.bjd_data_vencto_cbs,
(SELECT SUM(gcinfitens.item_valor_contratar)
FROM gcinfitens
WHERE gcinfitens.danfe = gcibjdnf.danfe) AS nf_vl_contratar,
(SELECT Max(id_contgrupo) FROM gcrcontitens WHERE gcrcontitens.danfe = gcibjdnf.danfe) AS id_contgrupo,
(SELECT MIN(nu_interv)
FROM gcrcondper
WHERE gcrcondper.id_cond = gcccond.id_cond
) AS nu_min_prz,
(SELECT MAX(nu_interv)
FROM gcrcondper
WHERE gcrcondper.id_cond = gcccond.id_cond
) AS nu_max_prz,
priper.vl_taxa AS nu_taxa,
priper.cd_tp_taxa,
priper.cd_indicador,
gcccond.nm_cond,
gcccond.cd_tp_ctr,
priper.sg_mod AS sg_mod_cond,
gcccond.dt_validade,
gcccond.cd_sit AS cd_sit_cond,
gcccond.nu_car_prz,
gcccond.cd_base_carencia,
gcccond.nu_car_desc,
apcconc.cd_loja,
apcconc.cd_concess,
apcconc.cd_conc_mat,
apcconc.nm_conc,
apcconc.nm_apelido,
apcconc.cd_tp_mercado,
dnccontrfundo.dt_emis_ctr
FROM gcibjdnf
LEFT JOIN apcconc ON TO_CHAR(apcconc.cd_sap_dealer) = gcibjdnf.dealer_sap
LEFT JOIN gcccond ON gcccond.id_cond = gcibjdnf.id_cond
LEFT JOIN dnccontrfundo ON dnccontrfundo.danfe = gcibjdnf.danfe
AND dnccontrfundo.cd_sit NOT IN ('CA','RE')
LEFT JOIN gcrcondper priper ON priper.id_cond = gcccond.id_cond
AND priper.sq_per = 1
WHERE (( apcconc.cd_concess = '1586297'
OR apcconc.cd_conc_mat = '1586297') AND gcibjdnf.bjd_situacao = 'I' AND bjd_sit_interna IN ('NO', 'SD'))
ORDER BY apcconc.nm_apelido, danfe
答案 0 :(得分:2)
移动此行:
LEFT JOIN gcccond ON gcccond.id_cond = gcibjdnf.id_cond
第一个联接:
FROM
gcibjdnf
LEFT JOIN gcccond ON gcccond.id_cond = gcibjdnf.id_cond
..................................
由于您订购联接的方式,在这些行中:
.....................
LEFT JOIN gcrcondper gmin ON gmin.id_cond = gcccond.id_cond
LEFT JOIN gcrcondper gmax ON gmax.id_cond = gcccond.id_cond
.........................................................
您正在尝试使用查询中尚未定义的表的列gcccond.id_cond
。
因此FROM
子句必须为:
FROM
gcibjdnf
LEFT JOIN gcccond ON gcccond.id_cond = gcibjdnf.id_cond
LEFT JOIN gcinfitens ON gcinfitens.danfe = gcibjdnf.danfe
LEFT JOIN gcrcontitens ON gcrcontitens.danfe = gcibjdnf.danfe
LEFT JOIN gcrcondper gmin ON gmin.id_cond = gcccond.id_cond
LEFT JOIN gcrcondper gmax ON gmax.id_cond = gcccond.id_cond
LEFT JOIN apcconc ON TO_CHAR(apcconc.cd_sap_dealer) = gcibjdnf.dealer_sap
LEFT JOIN dnccontrfundo ON dnccontrfundo.danfe = gcibjdnf.danfe
AND dnccontrfundo.cd_sit NOT IN ('CA', 'RE')
LEFT JOIN gcrcondper priper ON priper.id_cond = gcccond.id_cond
AND priper.sq_per = 1
此外,在ORDER BY
子句中,您还有不合格的列danfe
。
您必须使用表的名称/别名(例如dnccontrfundo.danfe
或gcibjdnf.danfe
)对其进行限定。
答案 1 :(得分:1)
我喜欢将这样的查询分解成较小的部分,修复一个问题,然后添加另一个修复点点滴滴的内容。
我将从FROM位开始:
select *
FROM gcibjdnf
LEFT JOIN apcconc
ON TO_CHAR(apcconc.cd_sap_dealer) = gcibjdnf.dealer_sap
LEFT JOIN gcccond
ON gcccond.id_cond = gcibjdnf.id_cond
LEFT JOIN dnccontrfundo
ON dnccontrfundo.danfe = gcibjdnf.danfe
AND dnccontrfundo.cd_sit NOT IN ('CA','RE')
LEFT JOIN gcrcondper priper
ON priper.id_cond = gcccond.id_cond
AND priper.sq_per = 1
WHERE (
(apcconc.cd_concess = '1586297' OR apcconc.cd_conc_mat = '1586297')
AND gcibjdnf.bjd_situacao = 'I'
AND gcibjdnf.bjd_sit_interna IN ('NO', 'SD') -- assume bjd_sit_interna is in gcibjdnf
)
您应该完全限定bjd_sit_interna的资格,以便所有人都知道它在哪个表中。
我创建的表仅带有此处命名的列。该查询的这一部分似乎“起作用”,只是逻辑不一致。
接下来,我添加了ORDER BY子句。
ORDER BY apcconc.nm_apelido, gcibjdnf.danfe; -- danfe must be fully qualified, else ambiguous
现在在SELECT列表中,您没有任何直接聚合函数;您只能将它们放在标量子查询中。因此,您不需要,而且在整个查询的末尾也必须没有GROUP BY!
实际上,您的查询将按原样运行,但ORDER BY中的歧义列除外。
但是,由于您在gcrcondper上的MIN和MAX子查询可以访问不符合JOIN条件的行,因此您可能会得到奇怪的结果。您确定那是您想要的吗?
除了不一致的JOIN逻辑和这种MIN / MAX怪异之外,您的查询也应该可以使用。在讨论性能之前,请查看逻辑以确保查询提供了所需的结果。