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

但是你没有意识到你也有一个间接连接

选择加入 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

所以join的循环间接地加入了elf to ropt。一种方法是为 elf 与 forn 进行外部连接,但最后了解您的要求然后连接表是有意义的。

- 编辑 -

正如所指出的,我们不能有 2 个外连接,一个(丑陋的)解决方法可能是这样的

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

我建议你学习和使用 ANSI 风格的连接运算符,如 INNER JOIN、LEFT OUTER JOIN 等。它们比将所有内容都放在 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 子句中的三个比较可以放入连接中 - 我将它们放在 WHERE 子句中以证明您可以这样做。我怀疑优化器会根据需要使用这些比较。

分享和享受。

- - 编辑

另请注意,将表“elf”的两个条件放在 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 回答