这是一个最小的设置,有 2 个表a,b每个表有 3 行:
CREATE TABLE a (
id SERIAL PRIMARY KEY,
value TEXT
);
CREATE INDEX ON a (value);
CREATE TABLE b (
id SERIAL PRIMARY KEY,
value TEXT
);
CREATE INDEX ON b (value);
INSERT INTO a (value) VALUES ('x'), ('y'), (NULL);
INSERT INTO b (value) VALUES ('y'), ('z'), (NULL);
Run Code Online (Sandbox Code Playgroud)
这是一个按预期工作正常的 LEFT JOIN:
SELECT * FROM a
LEFT JOIN b ON a.value IS NOT DISTINCT FROM b.value;
Run Code Online (Sandbox Code Playgroud)
带输出:
id | value | id | value
----+-------+----+-------
1 | x | |
2 | y | 1 | y
3 | | 3 |
(3 rows)
Run Code Online (Sandbox Code Playgroud)
将“LEFT JOIN”更改为“FULL JOIN”会出现错误:
SELECT * FROM a
FULL JOIN b ON a.value IS NOT DISTINCT FROM b.value;
Run Code Online (Sandbox Code Playgroud)
错误:FULL JOIN 仅支持可合并连接或可哈希连接的连接条件
有人可以回答吗:
什么是“可合并连接或可哈希连接的连接条件”,为什么加入a.value IS NOT DISTINCT FROM b.value不满足此条件,但a.value = b.value完全没问题?
似乎唯一的区别是如何处理 NULL 值。由于该value列在两个表中都有索引,因此EXPLAIN在NULL查找上运行与查找非值一样有效NULL:
EXPLAIN SELECT * FROM a WHERE value = 'x';
QUERY PLAN
--------------------------------------------------------------------------
Bitmap Heap Scan on a (cost=4.20..13.67 rows=6 width=36)
Recheck Cond: (value = 'x'::text)
-> Bitmap Index Scan on a_value_idx (cost=0.00..4.20 rows=6 width=0)
Index Cond: (value = 'x'::text)
EXPLAIN SELECT * FROM a WHERE value ISNULL;
QUERY PLAN
--------------------------------------------------------------------------
Bitmap Heap Scan on a (cost=4.20..13.65 rows=6 width=36)
Recheck Cond: (value IS NULL)
-> Bitmap Index Scan on a_value_idx (cost=0.00..4.20 rows=6 width=0)
Index Cond: (value IS NULL)
Run Code Online (Sandbox Code Playgroud)
这已经用 PostgreSQL 9.6.3 和 10beta1 测试过。
PostgreSQLFULL OUTER JOIN使用散列或合并连接来实现。
要符合此类加入的条件,加入条件必须具有以下形式
<expression using only left table> <operator> <expression using only right table>
Run Code Online (Sandbox Code Playgroud)
现在您的连接条件确实看起来像这样,但是 PostgreSQL 没有特殊的IS NOT DISTINCT FROM运算符,因此它将您的条件解析为:
(NOT ($1 IS DISTINCT FROM $2))
Run Code Online (Sandbox Code Playgroud)
并且这样的表达式不能用于散列或合并连接,因此会出现错误消息。
我可以想出一种方法来解决它:
SELECT a_id, NULLIF(a_value, '<null>'),
b_id, NULLIF(b_value, '<null>')
FROM (SELECT id AS a_id,
COALESCE(value, '<null>') AS a_value
FROM a
) x
FULL JOIN
(SELECT id AS b_id,
COALESCE(value, '<null>') AS b_value
FROM b
) y
ON x.a_value = y.b_value;
Run Code Online (Sandbox Code Playgroud)
如果<null>未出现在value列中的任何位置,则有效。
| 归档时间: |
|
| 查看次数: |
6019 次 |
| 最近记录: |