【问题标题】:Anti Join based on multiple keys / columns (SQL)基于多键/多列的反连接(SQL)
【发布时间】:2020-02-20 13:19:41
【问题描述】:

设置很简单,我想从table A 中检索table B 中不存在的所有行。因为可以使用 4 列来标识唯一行,所以我需要有一种方法来编写它可以正常工作的 WHERE 语句。

我的解决方案是连接 4 列并将其用作“一个”列/键来进行外部连接:

select      * 
from        table_A
where       filter_condition = 0
and         (column1 || column2 || column3 || column4) not in (
            select          A.column1 || A.column2 || A.column3 || A.column4
            from            table_A A -- 1618727
            inner join      table_B B
            on              A.column1 = B.column1 
            and             A.column2 = B.column2 
            and             A.column3 = B.column3 
            and             A.column4 = B.column4
            and             filter_condition = 0
            )

我的问题是,这是这样做的好方法还是我在做一些根本错误的事情?

需要明确的是,想要的结果只是只取回由于INNER JOIN 与 table_A 和 table_B 而“丢失”的 table_A 的行。

【问题讨论】:

  • filter_condition 列属于哪个表?
  • 是否涉及空值?
  • 请注意'AB' || 'C' = 'A' || 'BC',但('AB', 'C') <> ('A', 'BC')
  • 这是一个常见问题解答。在考虑发布之前,请始终使用谷歌搜索您的错误消息或您的问题/问题/目标的许多清晰、简洁和精确的措辞,有或没有您的特定字符串/名称和站点:stackoverflow.com 和标签,并阅读许多答案。如果您发布问题,请使用一个短语作为标题。请参阅How to Ask 和投票箭头鼠标悬停文本。

标签: sql postgresql subquery inner-join


【解决方案1】:

你好像在找not exists

select a.* 
from table_a a
where a.filter_condition = 0
and not exists (
    select 1
    from table_b b
    where 
        a.column1 = b.column1 
        and a.column2 = b.column2 
        and a.column3 = b.column3 
        and a.column4 = b.column4
)

这将为您提供table_a 中在table_b 中没有相应记录的所有记录。

【讨论】:

  • 这似乎是最安全和最好的解决方案,因为它返回了我正在寻找的两行(而不是很多其他行)。已将我的问题标记为重复,给您带来的不便深表歉意。
【解决方案2】:

您应该能够在 PostgreSQL 中使用元组(也称为行构造函数):

select * 
from table_a
where filter_condition = 0
and (column1, column2, column3, column4) not in
(
  select column1, column2, column3, column4
  from table_b
);

如果列可以为空,则最好使用NOT EXISTS,因为 null=null 会导致“未知”而不是真或假。

【讨论】:

  • 元组比较正确处理空值:rextester.com/XDWI48444
  • @a_horse_with_no_name:啊,太好了。谢谢你检查这个。因此,只有当 all 这些列在 table_b 行中为空时,这才会成为问题。
  • 正确,在这种情况下,我们又回到了旧的“不存在问题”的空值。
【解决方案3】:

AB 之间使用LEFT JOIN 并检查B 中的NULL 行可能更容易:

SELECT *
FROM table_A A
LEFT JOIN table_B B ON A.column1 = B.column1 
                   AND A.column2 = B.column2 
                   AND A.column3 = B.column3 
                   AND A.column4 = B.column4
WHERE B.column1 IS NULL
  AND A.filter_condition = 0

【讨论】:

    猜你喜欢
    • 2021-02-01
    • 1970-01-01
    • 2023-02-14
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 2013-03-15
    • 2011-10-07
    • 1970-01-01
    相关资源
    最近更新 更多