Самостоятельное объединение в SQL Oracle; Почему правое внешнее объединение не сохраняет все значения таблицы

Я не понимаю, почему правое внешнее соединение (из приведенного ниже примера) не дает полный набор данных таблицы, как левое внешнее соединение; поскольку внешние объединения всегда сохраняют строки соответствующей таблицы.

Создать таблицу

create table join_test
(id number unique not null, name varchar2(10), department varchar2(10));

Заполнить таблицу

select * from join_test;

   ID NAME            DEPARTMENT   
    1 stelios          sa 
    2 andros           sa 
    3 stav             ba  
    4 mary             ba  
    5 antonia          la  
    6 lambros          ka  

Внутреннее соединение

select j1.name, j1.department
from join_test j1 join join_test j2
on(j1.department=j2.department and j1.name<>j2.name);

   NAME         DEPARTMENT
   andros          sa
   steliso         sa
   mary            ba
   stav            ba

Левое внешнее соединение

select j1.name, j1.department
from join_test j1 left join join_test j2
on(j1.department=j2.department and j1.name<>j2.name)

   NAME       DEPARTMENT
   andros     sa
   steliso    sa
   mary       ba
   stav       ba
   antonia    la
   lambros    ka

Правое внешнее соединение

select j1.name, j1.department
from join_test j1 right join join_test j2
on(j1.department=j2.department and j1.name<>j2.name)

   NAME       DEPARTMENT
   steliso    sa
   andros     sa
   stav       ba
   mary       ba

Изменение списка выбора на j2

select j2.name, j2.department
from join_test j1 right join join_test j2
on(j1.department=j2.department and j1.name<>j2.name)

 NAME       DEPARTMENT
 andros     sa
 steliso    sa
 mary       ba
 stav       ba
 antonia    la
 lambros    ka

3 ответа

Решение

Правое и левое соединения выполняют одну и ту же функцию. Что отличается в ваших примерах - это таблицы, из которых вы ВЫБИРАЕТЕ.

Эти два запроса:

select j2.name,j2.department
from join_test j1 left join join_test j2
on(j1.department=j2.department and j1.name<>j2.name)

а также

select j1.name,j1.department
from join_test j1 right join join_test j2
on(j1.department=j2.department and j1.name<>j2.name)

Произведите тот же результат:

NAME    DEPARTMENT
stelios sa
andros  sa
stav    ba
mary    ba
(null)  (null)
(null)  (null)

Причина различий в результатах, которые вы видите между вашими левым и правым запросами, заключается в том, что в левом примере вы выбираете из таблицы "вождения" (левая таблица, J1). Объединение показывает все строки из управляющей таблицы (J1) и совпадающие строки (которые не отображаются) из правой или неприводной таблицы (J2).

В вашем правильном примере вы меняете соединение, но все еще выбираете из J1. Поскольку J1 теперь является неприводной таблицей, вы видите только совпадающие результаты J1. Если вы добавите столбцы J2 в выборку, вы увидите все ее строки:

NAME        DEPARTMENT   NAME       DEPT
stelios     sa           andros     sa
andros      sa           stelios    sa
stav        ba           mary       ba
mary        ba           stav       ba
(null)      (null)       antonia    la
(null)      (null)       lambros    ka

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

В обоих случаях (нулевые) строки представляют строки из таблицы управления, которые не соответствуют таблице управления.

Это дает правильные результаты в SQL Fiddle (sqlfiddle.com/#!4/1e7075/2). Однако у меня есть подозрение. Возвращенные результаты:

NAME    DEPARTMENT
stelios sa
andros  sa
stav    ba
mary    ba
(null)  (null)
(null)  (null)

Я подозреваю, что как бы вы ни возвращали результаты (или смотрели на них), строки со всеми NULL значения игнорируются. Попробуйте выбрать столбцы из j2 стол и посмотреть, если вы получите больше результатов.

здесь вы делаете самосоединение и комбинируете его с правильным внешним соединением с неравными условиями соединения;

Из того, что я понял: когда он запрашивает правильное соединение, это означает, что он будет извлекать записи только с правой стороны таблицы, где есть строки, соответствующие условиям соединения, и объединять их со строками с левой стороны (основная таблица) где условия соблюдены.

А также потому, что основная таблица - это таблица с левой стороны от, поэтому, когда вы выполняете левое соединение, она извлекает все записи из левой таблицы (основной таблицы) + записи из правой таблицы, где есть строки соответствуют условиям соединения.

Когда дело доходит до внутреннего соединения, оно будет извлекать только совпадающие записи (строки), в которых выполняются условия соединения из обеих таблиц. Даже основная таблица является левой таблицей, все равно строки из левой таблицы, где не выполняются условия, не будут включены в наборы результатов.

Мне потребовалось некоторое время, чтобы понять это, и я надеюсь, что это хорошо объясняет и может быть полезно (COZ, я также изо всех сил пытался понять это раньше).

Другие вопросы по тегам