从旧式改为新式连接

时间:2018-01-25 16:45:24

标签: sql join plsql right-join

我一直在尝试将旧的SQL样式从交叉更改为联接,但我无法使其工作。

这是我的代码:

SELECT 'EFE' tipo,
    c.empnum,
    c.succlave,
    d.tipopago,
    d.tjcredito
FROM detcobros d,
    cobros c,
    masterbancos b,
    monedas m
WHERE     d.empnum = c.empnum
    AND d.succlave = c.succlave
    AND d.cobfolio = c.cobfolio
    AND d.PaisClave = b.PaisClave(+)
    AND d.bannum = b.bannum(+)
    AND d.monNum = m.monNum
    AND d.tipopago = 'EF'
    AND (   (c.status IN ('AU', 'US', 'UP'))
         OR (    c.status = 'CA'
             AND NVL (c.cortecaja, 0) <> NVL (c.cortecajacanc, 0)))
    AND c.empnum = 255
    AND c.succlave = 'CDCU'
    AND c.cortecaja = 3004

在这里我尝试过:

SELECT 'EFE' tipo,
    c.empnum,
    c.succlave,
    d.tipopago,
    d.tjcredito
FROM detcobros d
    JOIN cobros c ON c.empnum   = d.empnum
    and c.succlave = d.succlave
    and c.cobfolio = d.cobfolio
    RIGHT JOIN masterbancos b ON b.PaisClave = d.PaisClave
    and  b.bannum    = d.bannum
    JOIN monedas m ON m.monNum  = d.monNum
WHERE d.tipopago = 'EF'
    AND (   (c.status IN ('AU', 'US', 'UP'))
         OR (    c.status = 'CA'
             AND NVL (c.cortecaja, 0) <> NVL (c.cortecajacanc, 0)))
    AND c.empnum = 255
    AND c.succlave = 'CDCU'
    AND c.cortecaja = 3004

第一个查询返回数据但第二​​个查询没有获得任何数据。

3 个答案:

答案 0 :(得分:3)

使用LEFT JOIN尝试,因为+运算符在右侧。

syntax + operator

答案 1 :(得分:1)

如上所述,请考虑您希望从每个表中获取的数据集中的数据。

基本上,SQL引擎将按以下基本顺序处理您的查询:

FROM (incl JOINs) -> CONNECT BY -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY

对于您的查询,我建议您将所有相关条件移至JOIN,以最大限度地减少JOIN组合的数据集。

我建议:

SELECT 'EFE' AS tipo
    , c.empnum
    , c.succlave
    , d.tipopago
    , d.tjcredito
FROM detcobros d
INNER JOIN cobros c ON d.empnum = c.empnum
    AND d.succlave = c.succlave
    AND d.cobfolio = c.cobfolio
    AND c.empnum = 255
    AND c.succlave = 'CDCU'
    AND c.cortecaja = 3004
    AND (   
          c.status IN ('AU', 'US', 'UP')
          OR (
              c.status = 'CA'
              AND NVL (c.cortecaja, 0) <> NVL (c.cortecajacanc, 0)
          )
    )
LEFT OUTER JOIN masterbancos b ON d.PaisClave = b.PaisClave
    AND d.bannum = b.bannum
INNER JOIN monedas m ON d.monNum = m.monNum
WHERE d.tipopago = 'EF'

这确实包含了我自己的一些个人偏好设置(例如在AS列别名中使用SELECT但在表别名中没有使用{。另外,我相信您的查询已在JOIN monedas m ON m.monNum = d.monNum处中断。您指定了查询之间有两种不同类型的JOIN

答案 2 :(得分:1)

这是我得到的:

select 'EFE' tipo
     , c.empnum
     , c.succlave
     , d.tipopago
     , d.tjcredito
from   cobros c
       join detcobros d
            on   d.empnum = c.empnum
            and  d.succlave = c.succlave
            and  d.cobfolio = c.cobfolio
       join monedas m
            and  m.monnum = d.monnum
       left join masterbancos b
            and  b.paisclave = d.paisclave
            and  b.bannum = d.bannum
where  c.empnum = 255
and    c.succlave = 'CDCU'
and    c.cortecaja = 3004
and    d.tipopago = 'EF'
and    (   (c.status in ('AU', 'US', 'UP'))
        or (c.status = 'CA' and nvl(c.cortecaja, 0) <> nvl(c.cortecajacanc, 0)) );

我个人的偏好是将外连接放在from子句的末尾。关键字outerinner也是多余的混乱,所以我从不使用它们。

cobros似乎是逻辑起点,因为它在where子句中具有最多的谓词。 (当然,优化者并不关心。)

右连接只是向后写的左连接。我从不使用它们,我只是以另一种(正常)方式安排桌子。

过滤条件保留在where子句中(除非它们适用于外连接,在这种情况下它们需要包含在连接中 - 但这里没有任何类似的东西)。我确信这可以用任何一种方式论证,但我喜欢看到单独列出的连接和过滤条件。

我也为你修好了你的旧式大写字母;)