Переход от старого стиля к новому
Я пытался изменить свой старый стиль 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 ответа
Попробуйте это с LEFT JOIN, потому что оператор + находится справа.
Как я уже упоминал выше, думайте о ваших данных в наборах данных, которые вы хотите получить из каждой таблицы.
По сути, механизм 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
с между запросами.
Вот что я получил:
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
пункт. Также ключевые слова outer
а также inner
лишний беспорядок, поэтому я никогда не использую их.
cobros
казалось логичным отправным пунктом, так как он имеет больше предикатов в where
пункт. (Оптимизатору все равно, конечно.)
Правое соединение - это просто левое соединение, написанное задом наперед. Я никогда ими не пользуюсь, я просто расставляю столы другим (нормальным) образом.
Условия фильтрации остаются в where
предложение (если только они не применяются к внешнему объединению, и в этом случае их необходимо включить в объединение - но здесь такого не было). Я уверен, что это можно утверждать в любом случае, но мне нравится видеть объединения и условия фильтрации, перечисленные отдельно.
Я также установил для вас заглавные буквы в старом стиле;)