Настройка SQL-запросов для нескольких соединений - PullRequest
0 голосов
/ 29 июня 2019

Пожалуйста, дайте мне знать, как я могу настроить этот запрос для повышения производительности / времени выполнения.

PS - он был разработан другим человеком и передан мне.

запрос прикреплен (я знаю, что он огромный!) -

Любая идея о том, как обрабатывать объединения и подзапросы с агрегатами, будет действительно полезной.

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

Ответы [ 2 ]

2 голосов
/ 29 июня 2019

Переместить эту строку:

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 голос
/ 30 июня 2019

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

Я начну с бита 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, чтобы все знали, в какой таблице он находится.

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

  • Вы выполняете LEFT JOIN для apcconc, поэтому, даже если в apcconc нет совпадений, вы должны вернуть строку.
  • У вас есть предложение WHERE, для которого требуется строка apccon, поэтому любые результаты без совпадения с apcconc будут отфильтрованы. По сути, ваше левое соединение стало внутренним соединением.

Затем я добавил предложение ORDER BY.

ORDER BY apcconc.nm_apelido, gcibjdnf.danfe; -- danfe must be fully qualified, else ambiguous

Теперь в списке SELECT у вас нет прямых агрегатных функций; они есть только в скалярных подзапросах. Таким образом, вам не нужно, и вы не должны иметь GROUP BY в конце вашего общего запроса!

На самом деле ваш запрос будет выполняться как есть, за исключением неоднозначного столбца в ORDER BY.

Однако вы можете получить странные результаты, поскольку ваши подзапросы MIN и MAX в gcrcondper могут обращаться к строкам, которые не соответствуют условию JOIN. Вы уверены, что это то, что вы хотите?

Вне противоречивой логики JOIN и этой странности MIN / MAX ваш запрос должен работать. Прежде чем говорить о производительности, просмотрите логику, чтобы убедиться, что запрос дает желаемые результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...