如果我有2个表A和B,请执行以下查询:
SELECT * FROM A FULL OUTER JOIN B ON A.pk = B.fk;
我知道结果的数量将是3种结果的总和:
但是,如果我在A上添加条件,例如:
SELECT * FROM A FULL OUTER JOIN B ON A.pk = B.fk WHERE A.field = value;
与上一个查询相比,第一组结果会发生什么?
对于某些行,不满足A上的条件。那些类型" 1"成为" 3"在形式(null,b)中,这些将完全从结果中丢弃吗?
答案 0 :(得分:0)
编写查询时,将按顺序编写不同的操作部分:
SELECT->FROM->WHERE->GROUP BY->HAVING->ORDER BY->LIMIT
但是查询是按顺序进行物理评估的:
FROM->WHERE->GROUP BY->SELECT->HAVING->ORDER BY->LIMIT
因此,对于FULL OUTER JOIN
,当您指定WHERE
子句时,它正在评估关于连接表结果的子句(通常为此创建临时表)。如果您希望行为是A
中返回的唯一匹配A.field = value
的记录,则需要先从A
选择这些记录,然后将该结果加入{{ 1}}表:
B
Here是一个SqlFiddle所以你可以看到。
答案 1 :(得分:0)
RECAP - 完全外部加入中使用的条件
我创建了最简单的场景,其中2个表包含匹配记录和双方不匹配,并测试了所有案例,在此sqlfiddle:http://sqlfiddle.com/#!3/901cd2/11
小提琴是基于@JRLambert的回答,我已经接受了答案。这个答案仅用于总结和保管。
以下是这个小提琴的SQL查询和解释(如果它有一天消失的话):
-- Basic full join
-- Returns (a,b) for matching records, and also (a, null) and (null, b)
-- for all records from A and B without matches
SELECT * FROM A
FULL OUTER JOIN B
ON A.pk = B.fk;
-- With condition in the ON clause
-- Only joins results (a,b) if conditions are satisfied on A.
-- The example returns :
-- 1. (a,b) only if A and B records are matched, and a.field = 0
-- 2. (a, null) for unmatched A records, and also all values of A with A.field != 0 (even if there is a matching B record)
-- 3. (null, b) for all unmatched B records, or with matching A records not satisfying the condition
SELECT * FROM A
FULL OUTER JOIN B
ON A.pk = B.fk AND A.field = 0;
-- With condition in the WHERE clause
-- Joins all matching record first, and return only pairs (a,b) and (a, null) if a satisfied the condition.
-- This example joins as the first "Basic full join", and then only returns rows with a satisfying the condition (meaning cannot be null)
SELECT * FROM A
FULL OUTER JOIN B
ON A.pk = B.fk
WHERE A.field = 0;
-- To select all join results satisfying the condition on A,
-- but keeping all B results as (null,b) whenever the condition is not true on A,
-- preselect keys before the join
SELECT *
FROM (SELECT A.pk FROM A WHERE A.field = 0) A
FULL OUTER JOIN B
ON A.pk = B.fk;