LEFT JOIN 之后的 ORACLE JOIN

ORACLE JOIN after LEFT JOIN

我有四个 table,其中三个通过 LEFT JOIN 连接到主文件。

SELECT ZADOCO, CADOCO, RDRORN, RDOORN, PDDOCO 
FROM PRODDTA.F1755 T2
        LEFT JOIN PRODDTA.F90CG503 TCSRMA ON TCSRMA.CAASTYP = 'R' AND TCSRMA.CADOCO = ZADOCO
        LEFT JOIN PRODDTA.F40051 TRMAOS ON (TCSRMA.CAKCOO = TRMAOS.RDRKCO AND TCSRMA.CARORN = TRMAOS.RDRORN AND TCSRMA.CADCTO = TRMAOS.RDRCTO)
            LEFT JOIN PRODDTA.F4311 ON (TRMAOS.RDOKCO = PDKCOO AND TO_NUMBER(TRIM(TRMAOS.RDOORN)) = PDDOCO AND TRMAOS.RDOCTO = PDDCTO AND TRMAOS.RDPOLN = PDLNID AND (PDLTTR, PDNXTR) NOT IN (('980', '999')))
            WHERE ZASTAW = '2' AND ZADOCO IN (172755, 1672095, 1675619)

这个查询可能会给我带来重复项,因为它们都是 LEFT。

如何限制结果,使 table F40051 取决于 F4311(即,如果 F4311 (PD) 不存在,它不会显示 F40051 (RD)),但仍显示值 1672095?如果我将 INNER JOIN 应用于 F4311...

SELECT ZADOCO, CADOCO, RDRORN, RDOORN, PDDOCO 
FROM PRODDTA.F1755 T2
        LEFT JOIN PRODDTA.F90CG503 TCSRMA ON TCSRMA.CAASTYP = 'R' AND TCSRMA.CADOCO = ZADOCO
        LEFT JOIN PRODDTA.F40051 TRMAOS ON (TCSRMA.CAKCOO = TRMAOS.RDRKCO AND TCSRMA.CARORN = TRMAOS.RDRORN AND TCSRMA.CADCTO = TRMAOS.RDRCTO)
            JOIN PRODDTA.F4311 ON (TRMAOS.RDOKCO = PDKCOO AND TO_NUMBER(TRIM(TRMAOS.RDOORN)) = PDDOCO AND TRMAOS.RDOCTO = PDDCTO AND TRMAOS.RDPOLN = PDLNID AND (PDLTTR, PDNXTR) NOT IN (('980', '999')))
            WHERE ZASTAW = '2' AND ZADOCO IN (172755, 1672095, 1675619)

...我会失去一条记录

添加子查询可能会影响我的性能,因为没有直接的 link,但是 SQL 需要 运行 中的整个 SELECT首先是子查询,这会使它变得非常慢。

有什么想法吗?

我偶然发现了一个解决方案:

Using left join and inner join in the same query

参考 Gajus 的回答。

基本上我们可以玩括号:

SELECT ZADOCO, CADOCO, RDRORN, RDOORN, PDDOCO 
FROM PRODDTA.F1755 T2
        LEFT JOIN PRODDTA.F90CG503 TCSRMA ON TCSRMA.CAASTYP = 'R' AND TCSRMA.CADOCO = ZADOCO
        LEFT JOIN (PRODDTA.F40051 TRMAOS
            JOIN PRODDTA.F4311 ON TRMAOS.RDOKCO = PDKCOO AND TO_NUMBER(TRIM(TRMAOS.RDOORN)) = PDDOCO AND TRMAOS.RDOCTO = PDDCTO AND TRMAOS.RDPOLN = PDLNID AND (PDLTTR, PDNXTR) NOT IN (('980', '999'))
            LEFT JOIN PRODDTA.F43121 ON PRMATC = '1' AND PDKCOO = PRKCOO AND PDDOCO = PRDOCO AND PDDCTO = PRDCTO AND PDLNID = PRLNID)
                ON TCSRMA.CAKCOO = TRMAOS.RDRKCO AND TCSRMA.CARORN = TRMAOS.RDRORN AND TCSRMA.CADCTO = TRMAOS.RDRCTO
            WHERE ZASTAW = '2' AND ZADOCO IN (172755, 1672095, 1675619)

结果:

在 sub-query:

中执行连接
SELECT ZADOCO,
       CADOCO,
       RDRORN,
       RDOORN,
       PDDOCO 
FROM   PRODDTA.F1755 T2
       LEFT JOIN PRODDTA.F90CG503 TCSRMA
       ON (   TCSRMA.CAASTYP = 'R'
          AND TCSRMA.CADOCO = ZADOCO)
       LEFT JOIN (
         SELECT * -- Name the columns you want.
         FROM   PRODDTA.F40051 TRMAOS
                JOIN PRODDTA.F4311
         ON (   TRMAOS.RDOKCO = PDKCOO
            AND TO_NUMBER(TRIM(TRMAOS.RDOORN)) = PDDOCO
            AND TRMAOS.RDOCTO = PDDCTO
            AND TRMAOS.RDPOLN = PDLNID
            AND (PDLTTR, PDNXTR) NOT IN (('980', '999')))
       )
       ON (   TCSRMA.CAKCOO = TRMAOS.RDRKCO
          AND TCSRMA.CARORN = TRMAOS.RDRORN
          AND TCSRMA.CADCTO = TRMAOS.RDRCTO)
WHERE  ZASTAW = '2'
AND    ZADOCO IN (172755, 1672095, 1675619)

或者 INNER JOIN 然后 RIGHT OUTER JOIN:

SELECT ZADOCO, CADOCO, RDRORN, RDOORN, PDDOCO 
FROM   PRODDTA.F4311
       INNER JOIN PRODDTA.F40051 TRMAOS
       ON (   TRMAOS.RDOKCO = PDKCOO
          AND TO_NUMBER(TRIM(TRMAOS.RDOORN)) = PDDOCO
          AND TRMAOS.RDOCTO = PDDCTO
          AND TRMAOS.RDPOLN = PDLNID
          AND (PDLTTR, PDNXTR) NOT IN (('980', '999')))
       RIGHT OUTER JOIN PRODDTA.F90CG503 TCSRMA
       ON (   TCSRMA.CAKCOO = TRMAOS.RDRKCO
          AND TCSRMA.CARORN = TRMAOS.RDRORN
          AND TCSRMA.CADCTO = TRMAOS.RDRCTO)
       RIGHT OUTER JOIN PRODDTA.F1755 T2
       ON (   TCSRMA.CAASTYP = 'R'
          AND TCSRMA.CADOCO = ZADOCO)
WHERE ZASTAW = '2' AND ZADOCO IN (172755, 1672095, 1675619)

db<>fiddle here