0

ELF テーブルとの JOIN 条件に違反していても、ROPT テーブルのすべてのレコードが表示されるようにしたいです。

  SELECT   1      
   FROM   conf_raggr_opztar ropt,
           tar_opzioni_tariffarie opt,
           conf_raggruppamenti_forn rgf,
           conf_forniture_rel_ragg forg,
           conf_forniture forn,
           conf_elementi_fatturabili elf,
           tar_voci_fatturabili vof,
           base_fasce_orarie fas
   WHERE       ropt.opt_opzione_tariffaria_id = opt.opt_opzione_tariffaria_id
           AND rgf.rgf_raggruppamento_forn_id = ropt.rgf_raggruppamento_forn_id
           AND forg.rgf_raggruppamento_forn_id = rgf.rgf_raggruppamento_forn_id
           AND forg.forn_fornitura_id = forn.forn_fornitura_id
           AND forn.forn_fornitura_id = 'QJlXmOFZPF3eAlAG'
           AND elf.ROPT_RAGGR_OPZTAR_ID(+) = ropt.ropt_raggr_opztar_id
           AND elf.COID_CONTRATTUARIO_ID(+) = ropt.COID_CONTRATTUARIO_ID
           AND elf.ROPT_DATA_INI(+) = ropt.ROPT_DATA_INI
           AND elf.edw_partition = forn.EDW_PARTITION
           AND elf.elf_flag_ann(+) = 'N'
           And  elf.ELF_DATA_VER_FIN = to_date('31/12/9999','DD/MM/YYYY')
           AND elf.VOF_VOCE_FATTURABILE_ID = vof.VOF_VOCE_FATTURABILE_ID
           AND fas.FAS_FASCIA_ORARIA_ID = elf.FAS_FASCIA_ORARIA_ID
ORDER BY ELF_VERSIONE desc;

* ANSI JOIN VERSION (最初のものと同じように動作します)

  SELECT   1
FROM CONF_RAGGR_OPZTAR ropt
   INNER JOIN TAR_OPZIONI_TARIFFARIE OPT
     ON (ropt.OPT_OPZIONE_TARIFFARIA_ID = opt.OPT_OPZIONE_TARIFFARIA_ID)
   INNER JOIN CONF_RAGGRUPPAMENTI_FORN rgf
     ON (rgf.RGF_RAGGRUPPAMENTO_FORN_ID = ropt.RGF_RAGGRUPPAMENTO_FORN_ID)
   INNER JOIN CONF_FORNITURE_REL_RAGG forg
     ON (forg.RGF_RAGGRUPPAMENTO_FORN_ID = rgf.RGF_RAGGRUPPAMENTO_FORN_ID)
   INNER JOIN CONF_FORNITURE forn
     ON (forg.FORN_FORNITURA_ID = forn.FORN_FORNITURA_ID)
   LEFT OUTER JOIN CONF_ELEMENTI_FATTURABILI elf
     ON (elf.ROPT_RAGGR_OPZTAR_ID = ropt.ROPT_RAGGR_OPZTAR_ID AND
         elf.COID_CONTRATTUARIO_ID = ropt.COID_CONTRATTUARIO_ID AND
         elf.ROPT_DATA_INI = ropt.ROPT_DATA_INI AND
         elf.EDW_PARTITION = forn.EDW_PARTITION)
--   LEFT OUTER JOIN TAR_VOCI_FATTURABILI vof
--     ON (elf.VOF_VOCE_FATTURABILE_ID = vof.VOF_VOCE_FATTURABILE_ID)
--   LEFT OUTER JOIN BASE_FASCE_ORARIE fas
--     ON (fas.FAS_FASCIA_ORARIA_ID = elf.FAS_FASCIA_ORARIA_ID)
   WHERE forn.FORN_FORNITURA_ID = 'QJlXmOFZPF3eAlAG' AND
         elf.ELF_FLAG_ANN = 'N' AND
         elf.ELF_DATA_VER_FIN = TO_DATE('31/12/9999','DD/MM/YYYY')
ORDER BY ELF_VERSIONE DESC; 
4

4 に答える 4

2

クエリを理解する必要があります

elf の直接結合に (+) を配置することで、「elf にデータがあってもかまわないので、ropt 行を表示したい」という記述に成功しました。

  AND elf.ROPT_RAGGR_OPZTAR_ID(+) = ropt.ropt_raggr_opztar_id
  AND elf.COID_CONTRATTUARIO_ID(+) = ropt.COID_CONTRATTUARIO_ID
  AND elf.ROPT_DATA_INI(+) = ropt.ROPT_DATA_INI

しかし、あなたが気づいていないのは、間接結合もあるということです

ropt が rgf に参加しました

AND rgf.rgf_raggruppamento_forn_id = ropt.rgf_raggruppamento_forn_id

rgf は forg に、forn に forn に、そして最後に forn から elf に参加しました

AND forg.rgf_raggruppamento_forn_id = rgf.rgf_raggruppamento_forn_id
AND forg.forn_fornitura_id = forn.forn_fornitura_id
AND elf.edw_partition = forn.EDW_PARTITION

したがって、joins のサイクルは、間接的に elf を ropt に結合します。1 つの方法は、elf から forn への外部結合も行うことですが、最終的には、要件を理解してからテーブルを結合することが理にかなっています。

- 編集 -

2 つの外部結合を持つことはできないと指摘したように、1 つの (醜い) 回避策は次のようなものです。

SELECT   1      
   FROM   
           tar_opzioni_tariffarie opt,
           conf_raggruppamenti_forn rgf,
           conf_forniture_rel_ragg forg,
           conf_forniture forn,
           (
           select * from //or columns needed 
       conf_raggr_opztar ropt,
           conf_elementi_fatturabili elf where 
       elf.ROPT_RAGGR_OPZTAR_ID(+) = ropt.ropt_raggr_opztar_id
           AND elf.COID_CONTRATTUARIO_ID(+) = ropt.COID_CONTRATTUARIO_ID
           AND elf.ROPT_DATA_INI(+) = ropt.ROPT_DATA_INI
           ) elf_ropt,
           tar_voci_fatturabili vof,
           base_fasce_orarie fas
   WHERE       elf_ropt.opt_opzione_tariffaria_id = opt.opt_opzione_tariffaria_id
           AND rgf.rgf_raggruppamento_forn_id = elf_ropt.rgf_raggruppamento_forn_id
           AND forg.rgf_raggruppamento_forn_id = rgf.rgf_raggruppamento_forn_id
           AND forg.forn_fornitura_id = forn.forn_fornitura_id
           AND forn.forn_fornitura_id = 'QJlXmOFZPF3eAlAG'
           AND elf_ropt.edw_partition(+) = forn.EDW_PARTITION
           AND elf_ropt.elf_flag_ann(+) = 'N' //is this needed actually?
           And  elf_ropt.ELF_DATA_VER_FIN = to_date('31/12/9999','DD/MM/YYYY')
           AND elf_ropt.VOF_VOCE_FATTURABILE_ID = vof.VOF_VOCE_FATTURABILE_ID
           AND fas.FAS_FASCIA_ORARIA_ID = elf_ropt.FAS_FASCIA_ORARIA_ID
ORDER BY ELF_VERSIONE desc;
于 2012-08-06T09:35:30.553 に答える
2

INNER JOIN、LEFT OUTER JOIN などの ANSI 形式の結合演算子を学習して使用することをお勧めします。これらは、すべてを WHERE 句に入れるよりもはるかに明確で理解しやすいものです。あなたの声明の場合、次のように書き直すことができると思います。

SELECT 1
   FROM CONF_RAGGR_OPZTAR ropt
   INNER JOIN TAR_OPZIONI_TARIFFARIE OPT
     ON (ropt.OPT_OPZIONE_TARIFFARIA_ID = opt.OPT_OPZIONE_TARIFFARIA_ID)
   INNER JOIN CONF_RAGGRUPPAMENTI_FORN rgf
     ON (rgf.RGF_RAGGRUPPAMENTO_FORN_ID = ropt.RGF_RAGGRUPPAMENTO_FORN_ID)
   INNER JOIN CONF_FORNITURE_REL_RAGG forg
     ON (forg.RGF_RAGGRUPPAMENTO_FORN_ID = rgf.RGF_RAGGRUPPAMENTO_FORN_ID)
   INNER JOIN CONF_FORNITURE forn
     ON (forg.FORN_FORNITURA_ID = forn.FORN_FORNITURA_ID)
   LEFT OUTER JOIN CONF_ELEMENTI_FATTURABILI elf
     ON (elf.ROPT_RAGGR_OPZTAR_ID = ropt.ROPT_RAGGR_OPZTAR_ID AND
         elf.COID_CONTRATTUARIO_ID = ropt.COID_CONTRATTUARIO_ID AND
         elf.ROPT_DATA_INI = ropt.ROPT_DATA_INI AND
         elf.EDW_PARTITION = forn.EDW_PARTITION AND
         elf.ELF_FLAG_ANN = 'N' AND
         elf.ELF_DATA_VER_FIN = TO_DATE('31/12/9999','DD/MM/YYYY'))
   LEFT OUTER TAR_VOCI_FATTURABILI vof
     ON (elf.VOF_VOCE_FATTURABILE_ID = vof.VOF_VOCE_FATTURABILE_ID)
   LEFT OUTER BASE_FASCE_ORARIE fas
     ON (fas.FAS_FASCIA_ORARIA_ID = elf.FAS_FASCIA_ORARIA_ID)
   WHERE forn.FORN_FORNITURA_ID = 'QJlXmOFZPF3eAlAG'
   ORDER BY ELF_VERSIONE DESC; 

上記の WHERE 句の 3 つの比較を結合に入れることができることに注意してください。結合できることを示すために、それらを WHERE 句に入れました。オプティマイザーは、これらの比較を必要に応じて使用すると思われます。

共有してお楽しみください。

- - 編集

また、テーブル 'elf' の 2 つの条件を WHERE 句に入れると、'elf' が強制的に内部結合されているかのように扱われることに注意してください。自分へのメモ: 将来的には少し教訓的でないようにしてください... :-)

于 2012-08-06T11:31:35.557 に答える
1

おそらく、ANSI JOIN のUSING コンストラクトを使用し、サブクエリを使用すると、クエリを簡単に記述できるようになります。

このサンプルを見てください。クエリが機能するはずです。

SELECT   1
FROM CONF_RAGGR_OPZTAR ropt
    JOIN TAR_OPZIONI_TARIFFARIE OPT using (OPT_OPZIONE_TARIFFARIA_ID)
    JOIN CONF_RAGGRUPPAMENTI_FORN rgf using (RGF_RAGGRUPPAMENTO_FORN_ID)
    JOIN CONF_FORNITURE_REL_RAGG forg using (RGF_RAGGRUPPAMENTO_FORN_ID)
    JOIN CONF_FORNITURE forn using (FORN_FORNITURA_ID)
    LEFT JOIN (
            select *
            from CONF_ELEMENTI_FATTURABILI 
            where ELF_FLAG_ANN = 'N' 
                AND ELF_DATA_VER_FIN = TO_DATE('31/12/9999','DD/MM/YYYY')
        ) elf using (ROPT_RAGGR_OPZTAR_ID,COID_CONTRATTUARIO_ID,ROPT_DATA_INI,EDW_PARTITION)
--   LEFT OUTER JOIN TAR_VOCI_FATTURABILI vof
--     ON (elf.VOF_VOCE_FATTURABILE_ID = vof.VOF_VOCE_FATTURABILE_ID)
--   LEFT OUTER JOIN BASE_FASCE_ORARIE fas
--     ON (fas.FAS_FASCIA_ORARIA_ID = elf.FAS_FASCIA_ORARIA_ID)
WHERE FORN_FORNITURA_ID = 'QJlXmOFZPF3eAlAG'
ORDER BY  elf.ELF_VERSIONE DESC; 

とにかく、CONF_ELEMENTI_FATTURABILI から列を選択していない場合、なぜそのテーブルを外部結合したいのでしょうか?

無意味じゃないですか!!!次のクエリでは、重複を除いて同じ結果が得られます。

SELECT   1
FROM CONF_RAGGR_OPZTAR ropt
    JOIN TAR_OPZIONI_TARIFFARIE OPT using (OPT_OPZIONE_TARIFFARIA_ID)
    JOIN CONF_RAGGRUPPAMENTI_FORN rgf using (RGF_RAGGRUPPAMENTO_FORN_ID)
    JOIN CONF_FORNITURE_REL_RAGG forg using (RGF_RAGGRUPPAMENTO_FORN_ID)
    JOIN CONF_FORNITURE forn using (FORN_FORNITURA_ID)
--   LEFT OUTER JOIN TAR_VOCI_FATTURABILI vof
--     ON (elf.VOF_VOCE_FATTURABILE_ID = vof.VOF_VOCE_FATTURABILE_ID)
--   LEFT OUTER JOIN BASE_FASCE_ORARIE fas
--     ON (fas.FAS_FASCIA_ORARIA_ID = elf.FAS_FASCIA_ORARIA_ID)
WHERE FORN_FORNITURA_ID = 'QJlXmOFZPF3eAlAG'
ORDER BY  null DESC; 
于 2012-08-06T17:05:30.233 に答える
0

私があなたの質問を正しく理解したなら、あなたはを使いたいでしょうLEFT JOIN

于 2012-08-06T09:14:19.923 に答える