我希望即使违反了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;
答案 0 :(得分:2)
您需要了解您的查询
通过将(+)放入elf的直接连接中,您已成功提及"我不在乎精灵是否有数据,我想显示ropt row"
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,forg to forn,最后forn to 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
因此,连接循环间接地将elf加入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;
答案 1 :(得分: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子句中以证明您可以这样做。我怀疑优化器会根据需要使用这些比较。
分享并享受。
----编辑
另请注意,在WHERE子句中放置表'elf'的两个条件会强制'elf'被视为内部连接。自我注意:将来尝试减少教学......: - )
答案 2 :(得分:1)
使用ANSI JOIN的USING construct和子查询的使用可能会使您的查询更容易编写。
查看此示例,它应该让您的查询工作。
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;
答案 3 :(得分:0)
如果我理解你的问题,你想使用LEFT JOIN
。