Имитация FULL OUTER JOIN: производительность UNION из LEFT + RIGHT JOIN против кросс-соединения - PullRequest
0 голосов
/ 11 мая 2018

ядро ​​базы данных Access / Jet не поддерживает FULL OUTER JOIN s:

SELECT Table1.*, Table2.*
FROM Table1
FULL OUTER JOIN Table2 ON Table1.JoinField = Table2.JoinField

Обычно рекомендуемая альтернатива - UNION результаты LEFT и RIGH JOIN s;возможны некоторые различия в следующем:

SELECT Table1.*, Table2.*
FROM Table1
LEFT JOIN Table2 ON Table1.JoinField = Table2.JoinField

UNION ALL 
SELECT Table1.*, Table2.*
FROM Table1
RIGHT JOIN Table2 ON Table1.JoinField = Table2.JoinField
WHERE Table1.JoinField IS NULL

Однако нельзя ли использовать перекрестное соединение?

SELECT Table1.*, Table2.*
FROM Table1, Table2
WHERE Table1.JoinField = Table2.JoinField
    OR Table1.JoinField IS NULL
    OR Table2.JoinField IS NULL

Существуют ли какие-либо потери производительности или другие недостатки использования перекрестного соединения?присоединиться таким образом?

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Поскольку я использую Redshift, может быть синтаксическая разница.

With a as
(
Select 1 id union all
Select 2 union all
Select 3 
)
, b as 
(
Select 2 d union all
Select 4 union all
Select 5 
)
Select a.*,b.* 
From a full join b on id=d

Выход

id  d
1   NULL
2   2
3   NULL
NULL    4
NULL    5

Если вы запустите

Select a.*,b.* 
from a 
left join b on id=d 
union all
Select  a.*,b.* 
from b 
left join a on d=id

Вы получаете

id  d
1   NULL
2   2
3   NULL
2   2
NULL    4
NULL    5

Но если вы объединитесь, вы получите тот же результат.

0 голосов
/ 11 мая 2018

Ваше кросс-соединение вовсе не FULL OUTER JOIN. Это внутреннее соединение, которое также соответствует NULL для всех записей.

В CROSS JOIN строки из одной таблицы всегда сопоставляются со строками из другой таблицы, в то время как в FULL OUTER JOIN есть строки, которые ничем не соответствуют.

Для иллюстрации я создал небольшой образец (T-SQL, но это не актуально). Вы можете видеть, что возвращается неравный ряд.

Однако вы можете использовать CROSS JOIN для эмуляции FULL OUTER JOIN, если нет значений Null, добавив строку Null, используя NOT EXISTS и некоторые другие приемы. Однако вы увидите, что это очень сложное решение, и обычно предпочитается обычный UNION:

SELECT *
FROM (SELECT * FROM #Table1 UNION ALL SELECT Null, Null) t1, (SELECT * FROM #Table2 UNION ALL SELECT Null, Null) t2
WHERE (t1.JoinField = t2.JoinField
OR (NOT EXISTS(SELECT 1 FROM #Table2 WHERE #Table2.JoinField = t1.JoinField) AND t1.JoinField Is Not Null AND t2.JoinField IS NULL)
OR (NOT EXISTS(SELECT 1 FROM #Table1 WHERE #Table1.JoinField = t2.JoinField) AND t2.JoinField Is Not Null AND t1.JoinField IS NULL))
AND (t1.JoinField Is Not Null Or t2.JoinField Is Not Null) 

(в связанном примере вы можете увидеть его в действии)

...