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

2024-06-19

这是包含 2 个表的最小设置a and 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);

这是一个按预期工作正常的 LEFT JOIN:

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

与输出:

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

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

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

错误:仅在可合并连接或可散列连接的连接条件下才支持 FULL JOIN

有人可以回答吗:

什么是“可合并连接或可哈希连接连接条件”以及为什么要连接a.value IS NOT DISTINCT FROM b.value不满足这个条件,但是a.value = b.value完全没问题吗?

似乎唯一的区别是 NULL 值的处理方式。自从value列在两个表中都建立了索引,运行EXPLAIN on a 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)

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

已经有关于这个问题的讨论 https://www.postgresql.org/message-id/20060313104028.GB6714@svana.org,但它并没有直接回答上述问题。


PostgreSQL 实现FULL OUTER JOIN使用哈希或合并连接。

要获得此类加入的资格,加入条件必须采用以下形式

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

现在你的加入条件does看起来像这样,但是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列。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 PostgreSQL 不能做这个简单的 FULL JOIN 呢? 的相关文章

  • 获取两行之间不同的列

    我有一张桌子company有 60 列 目标是创建一个工具来查找 比较和消除该表中的重复项 示例 我发现 2 家公司可能相同 但我需要知道这两行之间哪些值 列 不同才能继续 我认为可以逐列比较 x 60 但我寻找更简单 更通用的解决方案 就
  • 与 iexact 一起使用时,Django get_or_create 无法设置字段

    我想用name iexact with get or create尽可能避免用户输入字段的重复 我的提供者模型有一个名称字段 我在其中使用get or create 查找工作正常 但在第一次创建实例时 如下面的 p1 Timber 示例 名
  • 如何确定在 Postgres 中使用什么类型的索引?

    我有一个 Postgres 数据库 其中有 2 列不是主键 也不能是主键 但进行了大量搜索 并与其他表中的 2 列进行比较 我相信这是向我的表添加索引的完美案例 我以前从未在数据库上使用过索引 所以我正在尝试学习执行此操作的正确方法 我了解
  • MySQL - 连接 a 或 b

    假设我有一个TABLE a其中一个COLUMN data是一个join其他 2 张桌子 TABLE b and TABLE c 因为我想得到一个COLUMN info in b or c 事情是a data将匹配only with b da
  • PostgreSQL 中的日期比较

    有没有办法比较同一个表中的两个日期 如下所示 SELECT FROM mytable WHERE date 1 date 2 我正在寻找最简单的方法来作为更新语句的一部分来执行此操作 是的 你可以这么做 就那么简单 看看date timeP
  • SQLAlchemy 无法连接到本地主机上的 Postgresql

    我确信这是一个很容易修复的错误 只要我能找到它在哪里 这是 Flask 应用程序的错误 11 58 18 web 1 ERROR xxxxxx core Exception on GET 11 58 18 web 1 Traceback m
  • 哪个数据库对复制的支持最好

    我对 MySQL 复制的功能有相当好的感觉 我想知道还有哪些其他数据库支持复制 以及它们与 MySQL 和其他数据库相比如何 我的一些问题是 复制是内置的还是附加组件 插件 复制是如何工作的 高级 MySQL 提供基于语句的复制 5 1 中
  • PostgreSQL 中的用户定义变量

    我有以下 MySQL 脚本 我想在 PostgreSQL 中实现 SET statement search address query PREPARE dynquery FROM statement EXECUTE dynquery DEA
  • 如何列出 PostgreSQL 中表的所有约束?

    如何列出 PostgreSQL 中表的所有约束 主键 外键 检查 唯一互斥 表的约束可以从目录 pg 约束 https www postgresql org docs current catalog pg constraint html使用
  • 使用 Node.js 在 Postgres 中更新插入

    我正在尝试使用带有 pg 扩展名的 node js 版本 0 5 4 在 postgres 数据库中进行插入或更新 到目前为止我有这个代码 client query text update users set is active 0 ip
  • 如何在Postgresql时间戳中存储Golang time.time?

    我可以知道如何存储time timePostgresql 中的对象 例如 SQL 查询 INSERT INTO UserAccount email login time VALUES email protected cdn cgi l em
  • MYSQL:如何从姓氏中找到player_id?

    我现在尝试使用非标准化 摘要 表中的数据填充 testMatch 表 如下 测试匹配表 Field Type Null Key Default Extra match id int 11 NO PRI NULL match date dat
  • PostgreSQL、Npgsql 返回 42601:“$1”处或附近的语法错误

    我正在尝试使用 Npgsql 和 或 Dapper 来查询表 但我不断遇到Npgsql PostgresException 42601 syntax error at or near 1 这是我用 NpgsqlCommand 尝试的结果 u
  • Postgres:跨行连接 JSONB 值?

    我正在掌握 Postgres gt 9 5 中的 JSONB 功能 并且很喜欢它 但遇到了障碍 我读过有关连接 JSON 字段的功能 所以 a 1 b 2 创造 a 1 b 2 但我想在多行的同一字段中执行此操作 例如 select row
  • Postgres 数据库中特殊的时区处理

    我的环境 I m in 法国巴黎 UTC 1 or CET It s 12am 00 00 我们在2016 年 11 月 25 日 My Postgres数据库托管于亚马逊网络服务 AWS RDS 在eu west 1 region 问题
  • 如何使用 pgAdmin 恢复 postgreSQL 转储文件?

    我有一个 dmp 文件 想要从中恢复数据库 使用 pgAdmin 我该怎么做 在 PgAdmin3 内 在您正在使用的服务器中创建一个新数据库 右键单击该数据库并选择 恢复 使用 浏览器 按钮选择 dmp 文件 选择 恢复 开始恢复数据库
  • 为什么 justify_interval('360 days'::interval) 结果 '1 年'

    因为某些原因justify interval now 2013 02 14 timestamptz 产生奇怪的结果 postgres select justify interval concat 365 4 1 days interval
  • 左连接,左表中没有重复行

    请看下面的查询 tbl 目录 Content Id Content Title Content Text 10002 New case Study New case Study 10003 New case Study New case S
  • 对时间序列数据重新采样

    我有一个以毫秒为单位的时间序列列表 我想对时间序列进行重新采样并对组应用平均值 我如何在 Postgres 中实现它 重新采样 是指聚合一秒或一分钟内的所有时间戳 一秒或一分钟内的所有行形成一组 表结构 date x y z Use dat
  • psycopg 错误,列不存在

    我不断收到这个 错误 psycopg2 ProgrammingError 列 someentry 不存在 该错误表明该列someentry不存在时someentry不是列 它只是要输入数据库的值 这是给出错误的代码 cur execute

随机推荐