[英]Simulating FULL OUTER JOIN: Performance of UNION of LEFT+RIGHT JOIN vs cross join
The Access / Jet database engine doesn't support FULL OUTER JOIN
s: Access / Jet数据库引擎不支持
FULL OUTER JOIN
:
SELECT Table1.*, Table2.*
FROM Table1
FULL OUTER JOIN Table2 ON Table1.JoinField = Table2.JoinField
The commonly recommended alternative is to UNION
the results of the LEFT
and RIGH JOIN
s; 通常推荐的替代方法是
UNION
LEFT
和RIGH JOIN
的结果。 some variation on the following: 在以下方面有一些变化:
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
However, isn't it also possible to use a cross join? 但是,是否也可以使用交叉联接?
SELECT Table1.*, Table2.*
FROM Table1, Table2
WHERE Table1.JoinField = Table2.JoinField
OR Table1.JoinField IS NULL
OR Table2.JoinField IS NULL
Are there any performance penalties or other downsides to using a cross join in this way? 以这种方式使用交叉联接是否会对性能造成任何不利影响?
Your cross join isn't a FULL OUTER JOIN
at all. 您的交叉
FULL OUTER JOIN
根本不是FULL OUTER JOIN
。 It's an inner join that also matches NULL to all records. 这是一个内部联接,也将NULL匹配到所有记录。
In a CROSS JOIN
, rows from one table are always matched with rows from another table, while in a FULL OUTER JOIN
, there are rows that are matched to nothing. 在
CROSS JOIN
,一个表中的行总是与另一表中的行匹配,而在FULL OUTER JOIN
,有任何行都不匹配。
To illustrate, I created a small sample (T-SQL, but that's not relevant). 为了说明,我创建了一个小样本 (T-SQL,但这无关紧要)。 You can see that an inequal row is returned.
您可以看到返回了不相等的行。
You can, however, use a CROSS JOIN
to emulate a FULL OUTER JOIN
, if there are no Null
values, by appending a Null
row, using NOT EXISTS
, and some more tricks. 但是,如果没有
Null
值,则可以使用CROSS JOIN
来模拟FULL OUTER JOIN
,方法是通过附加Null
行,使用NOT EXISTS
以及其他一些技巧来模拟。 You'll see, however, that this is a very elaborate solution, and the normal UNION
is usually preferred: 但是,您会看到这是一个非常复杂的解决方案,通常首选普通的
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)
(In the linked sample, you can see it in action) (在链接的示例中,您可以看到它的运行情况)
As I am using Redshift there may be syntax difference. 当我使用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
Output is 输出是
id d
1 NULL
2 2
3 NULL
NULL 4
NULL 5
If you run 如果你跑
Select a.*,b.*
from a
left join b on id=d
union all
Select a.*,b.*
from b
left join a on d=id
You get 你得到
id d
1 NULL
2 2
3 NULL
2 2
NULL 4
NULL 5
But if you union only you get same result. 但是,如果仅合并,您将得到相同的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.