为什么PostgreSQL不能做这个简单的FULL JOIN?

时间:2017-05-28 20:10:09

标签: postgresql join

这是一个最小化设置,包含2个表$('#myModal .modal-body').html($("[data-attr=1] > p").text()); a,每个表有3行:

b

这是一个LEFT JOIN,可以正常工作:

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);

带输出:

SELECT * FROM a
LEFT JOIN b ON a.value IS NOT DISTINCT FROM b.value;

将“LEFT JOIN”更改为“FULL JOIN”会出错:

 id | value | id | value 
----+-------+----+-------
  1 | x     |    | 
  2 | y     |  1 | y
  3 |       |  3 | 
(3 rows)

错误:只有merge-joinable或hash-joinable join条件支持FULL JOIN

有人可以回答:

什么是“合并可加入或可加入哈希的连接条件”以及为什么加入SELECT * FROM a FULL JOIN b ON a.value IS NOT DISTINCT FROM b.value; 不符合此条件,但a.value IS NOT DISTINCT FROM b.value完全正常?

似乎唯一的区别是如何处理NULL值。由于a.value = b.value列已在两个表中编入索引,因此在value查找上运行EXPLAIN与查找非NULL的值一样有效:

NULL

已经使用PostgreSQL 9.6.3和10beta1进行了测试。

已经有discussion about this issue,但它没有直接回答上述问题。

2 个答案:

答案 0 :(得分:2)

PostgreSQL使用散列或合并连接实现FULL OUTER JOIN

要获得此类加入的资格,加入条件必须为

格式
<expression using only left table> <operator> <expression using only right table>

现在您的连接条件 看起来像这样,但PostgreSQL没有特殊的IS NOT DISTINCT FROM运算符,因此它会将您的条件解析为:

(NOT ($1 IS DISTINCT FROM $2))

这样的表达式不能用于散列或合并连接,因此错误消息。

我可以想办法解决这个问题:

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;

如果<null>列中没有出现value,则该方法有效。

答案 1 :(得分:0)

我刚刚解决了这种情况,用&#34; TRUE&#34;替换ON条件,并移动原始&#34; ON&#34;将条件转换为WHERE子句。但是,我不知道这对性能的影响。