2017-01-24 4 views
0

У меня проблема с поиском запроса с внешним соединением, как и ожидалось.LEFT JOIN on Oracle

Данные:

TABLE a: 

    id 
    1 
    2 
    3 

TABLE b: 

    id aid 
    11 1 
    12 2 

TABLE c: 

    id bid 
    21 11 
    22 12 

Этот запрос:

SELECT * 
FROM 
    a 
    LEFT JOIN 
    b 
    ON a.id = b.aid 
    INNER JOIN c 
    ON b.id = c.bid 

Мне нужно, чтобы получить все a и где возможно b и c, как это:

a.id b.id b.aid c.id c.bid 
1  11  1  21  11 
2  12  2  22  12 
3  null null null null 

INNER JOIN просто является расширением b, когда предшествующий LEFT JOIN соответствует.

Вместо этого, я получаю:

a.id b.id b.aid c.id c.bid 
1  11  1  21  11 
2  12  2  22  12 

Без второго INNER JOIN я получаю, как и ожидалось:

a.id b.id b.aid 
1  11  1 
2  12  2 
3  null null 

Там, кажется, другое определение соединений между Oracle и MS SQL Server , (ВЫКЛЮЧАЕТСЯ, ЧТОБЫ НЕПРАВИЛЬНО)

Я не могу понять, как написать запрос, чтобы получить ожидаемый результат.

+1

Там нет никакой разницы в внутренней и левое соединение между Sql Server и Oracle – edc65

+4

я бы ** очень ** удивлен если SQL Server вернет для этого что-то другое. Вам нужно внешнее соединение для второго соединения, а также –

+1

(второй) внутренний joi не может присоединиться к нулевому значению для b.id .. так что ваше исправление кажется неправильным .. oracle и ms sql работают одинаково. join – scaisEdge

ответ

3

Это правильное поведение и SQL Server будет возвращать точно так же, результат. См. Онлайн-пример здесь: http://rextester.com/EEGBZ41105

Поскольку вы выполняете внутреннее соединение между b и c, это существенно нарушает внешнее соединение между a и b.

Если посмотреть на последней строке ожидаемого результата:

a.id b.id b.aid c.id c.bid 
3  null null null null 

А теперь посмотрим на условия присоединения b.id = c.bid это довольно ясно, что он удалит эту строку, так как значение b.id равно нулю из-за внешнее соединение между a и b, и, таким образом, внутреннее соединение снова удаляет эту строку.

Вы должны использовать внешнее соединение для соединения между б и в, а также:

SELECT * 
FROM a 
    LEFT JOIN b ON a.id = b.aid 
    LEFT JOIN c ON b.id = c.bid 
; 
+0

* стыдно за меня * :) Спасибо, вот и все! – pid

+0

Чтобы быть искренним, я понятия не имею, были ли включены ANSI_NULLS, где я работал раньше. Они также использовали сифонированные данные VB.NET от ACCESS в БД. Поэтому вполне возможно, что я прожил годами в мире, где «NULL = NULL», не заметив этого (в univ я очень хорошо узнал, что «NULL» не равен чему-либо еще). – pid

+0

@pid: я снял эту часть. Даже когда 'ansi_nulls' выключен, я не получаю другого результата –

1

Ваш запрос будет интерпретироваться как (обратите внимание на скобки):

SELECT * 
FROM 
    (
    a 
    LEFT JOIN 
    b 
    ON a.id = b.aid 
    ) 
    INNER JOIN c 
    ON b.id = c.bid 

Вместо этого, вы, вероятно, имел в виду:

SELECT * 
FROM 
    a 
    LEFT JOIN 
    (
    b 
    INNER JOIN c 
    ON b.id = c.bid 
    ) 
    ON a.id = b.aid 
+0

Да, это то, что я намеревался.Спасибо, другой ответ показывает, как получить результат! – pid