【问题标题】:Compare two tables with SQL while ignoring null columns使用 SQL 比较两个表,同时忽略空列
【发布时间】:2018-02-17 10:19:32
【问题描述】:

我想在 SQL (postgres) 中比较两个表的内容。这些表具有匹配的架构。作为输出,我想要那些不同的行。 我已经检查了各种方法(也有一些在 Stackoverflow 上发布),但在我看来,当两列中的字段均为 NULL 时,我遇到了问题。到目前为止,这是我想出的:

SELECT dipi.id AS dipi_id,dipi.foo AS dipi_foo,dipi.bar AS dipi_bar, rvdii.id AS rvdii_id,rvdii.foo AS rvdii_foo,rvdii.bar AS rvdii_bar
FROM schema1.mytable dipi
FULL OUTER JOIN schema2.mytable rvdii on dipi.id = rvdii.id AND dipi.foo = rvdii.foo AND dipi.bar = rvdii.bar
WHERE dipi.id is null or rvdii.id is null

因此,对所有列进行完全外连接,然后返回其中一个 ID 为空的列。

但是通过这个查询,我得到了一些示例数据:

dipi_id dipi_foo dipi_bar rvdii_id rvdii_foo rvdii_bar 3 2016-01-01 NULL NULL NULL NULL NULL NULL NULL 3 2016-01-01 NULL

如您所见,“dipi_bar”、“rvdii_bar”列包含一个空值,在连接中不匹配(据我了解)。因此,在上述情况下,我不想要任何输出,我希望当两个列/字段都为 NULL 时,它们在连接中得到“匹配”(或在连接中被忽略,不管怎样)。这样做的诀窍是什么?

编辑:当然该列并不总是空的,所以从连接中删除不是一个选项:)

【问题讨论】:

  • 如果我理解您的请求权,应该尝试与IS NOT DISTINCT FROM 结合使用自然加入,例如。 G。 dipi.foo IS NOT DISTINCT FROM rvdii.foo
  • 好主意,看起来这对于 postgres 是不可能的:“错误:FULL JOIN 仅支持可合并或可哈希连接的连接条件”我会尝试其他答案。
  • Ups,我写的很自然,但我的意思是 inner join,但我不建议使用 full outer join。

标签: sql postgresql


【解决方案1】:

我认为您想查看两个表中具有相同 id 的行,而在其他两个字段中存在差异。如果是这种情况,我认为以下内容可以完成这项工作:

SELECT dipi.id AS dipi_id,dipi.foo AS dipi_foo,dipi.bar AS dipi_bar, rvdii.id AS rvdii_id,rvdii.foo AS rvdii_foo,rvdii.bar AS rvdii_bar
FROM schema1.mytable dipi
INNER JOIN schema2.mytable rvdii on dipi.id = rvdii.id 
WHERE (dipi.foo <> rvdii.foo OR (dipi.foo IS NULL AND rvdii.foo IS NOT NULL) OR (dipi.foo IS NOT NULL AND rvdii.foo IS NULL))
OR (dipi.bar <> rvdii.bar OR (dipi.bar IS NULL AND rvdii.bar IS NOT NULL) OR (dipi.bar IS NOT NULL AND rvdii.bar IS NULL))

【讨论】:

    【解决方案2】:

    使用NULL-安全比较运算符is not distinct from。请注意,WHERE 子句也需要更改。 Postgres 没有 xor 运算符,但你可以这样做:

    SELECT dipi.id AS dipi_id,dipi.foo AS dipi_foo,dipi.bar AS dipi_bar,
           rvdii.id AS rvdii_id,rvdii.foo AS rvdii_foo,rvdii.bar AS rvdii_bar
    FROM schema1.mytable dipi FULL OUTER JOIN
         schema2.mytable rvdii 
         ON dipi.id IS NOT DISTINCT FROM rvdii.id AND
            dipi.foo IS NOT DISTINCT rvdii.foo AND
            dipi.bar IS NOT DISTINCT FROM rvdii.bar
    WHERE dipi.id IS DISTINCT FROM rvdii.id OR
          dipi.foo IS DISTINCT FROM rvdii.foo OR
          dipi.bar IS DISTINCT FROM rvdii.bar;
    

    由于代码允许在ON 中匹配NULL,因此您无法检查NULLWHERE 过滤条件。

    【讨论】:

    • Is not distinct from 不适用于 postgres 中的 FULL OUTER JOIN (请参阅我对原始问题的评论)。不过谢谢你的想法。我想我找到了一种使用 INTERSECT 和和 EXCEPT 运算符的工作方法。
    【解决方案3】:

    回答我自己的问题:我最终使用了https://stackoverflow.com/a/18736060/1368432 的方法,它使用UNIONEXCEPTINTERSECT 来获得正确的结果集。就我而言,这是最简单的方法。

    【讨论】:

    • 您可以使用这样的连接条件:coalesce(dipi.id, -42) = coalesce(rvdii.id, -42) 进行完全外部连接 - 但这要求您可以找到这些列中不存在的值。
    猜你喜欢
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多