【问题标题】:Converting a PostgreSQL query with IN / NOT IN to JOINs将带有 IN / NOT IN 的 PostgreSQL 查询转换为 JOIN
【发布时间】:2017-05-15 11:50:52
【问题描述】:

我目前有两个结构相同的表。表 A(例如)有 10,000 行,表 B 有 100,000 行。我需要获取表 B 中不在表 A 中的行,但前提是某些字段相同(而一个字段不同)。

现在,查询类似于:

select *
from tableA A
where (A.field1, A.field2) in (select field1, field2 from tableB B)
  and A.field3 not in (select field3 from B)

这行得通,但使用JOINs 可能会获得更好的性能解决方案。我试过这样做,但我得到的只是一个非常庞大的重复行列表。有人能指出我正确的方向吗?

【问题讨论】:

标签: sql postgresql select join


【解决方案1】:

根据您当前的查询,这就是它转换为联接的内容:

select * 
from tableA A
inner join tableB B on A.field1 = B.field1 and A.field2 = B.field2
left outer join tableB C on A.field3 = C.field3
where c.field3 is null

更快的查询是:

    select A.pk
    from tableA A
    inner join tableB B on A.field1 = B.field1 and A.field2 = B.field2
    left outer join tableB C on A.field3 = C.field3
    where c.field3 is null
    group by A.pk

这将为您提供需要添加到 tableB 的行,因为它们没有找到。

或者你可以只获取你想要拉过来的字段:

    select A.field1, A.field2, A.field3
    from tableA A
    inner join tableB B on A.field1 = B.field1 and A.field2 = B.field2
    left outer join tableB C on A.field3 = C.field3
    where c.field3 is null
    group by A.field1, A.field2, A.field3

【讨论】:

  • 如果在(field1, field2) 连接条件上AB 之间有保证的1:1 关系,这只是一个等效查询。
  • 也许需要 SELECT DISTINCT。 (取决于数据。)
  • 是的,我是有根据的猜测
  • 此查询需要很长时间才能运行并返回大量重复的行。我的查询或@joop 的查询按预期工作(需要 6-7 秒)。你认为它缺少什么? “SELECT DISTINCT”也需要很长时间。
  • tableA中有id列吗?因为我只会选择它而不是 * 并按该列进行分组,这样会更快
【解决方案2】:

[NOT] EXISTS 是你的朋友:


SELECT *
FROM tableA A
WHERE EXISTS ( SELECT * FROM tableB B
    WHERE A.field1 = B.field1
    AND A.field2 = B.field2
    )
AND NOT EXISTS ( SELECT * FROM tableB B 
    WHERE  A.field3 = B.field3 
    );

注意:如果连接的列不可为空,[NOT] EXISTS() 版本的行为将与 [NOT] IN 版本完全相同


一遍又一遍地阅读问题文本:

我需要获取表 B 中不在表 A 中的行,但前提是某些字段相同(而一个字段不同)。


SELECT *
FROM tableB B
WHERE EXISTS ( SELECT * FROM tableA A
        WHERE A.field1 = B.field1
        AND A.field2 = B.field2 
        AND  A.field3 <> B.field3
        );

【讨论】:

  • 谢谢,但不幸的是,此查询与原始查询所用的时间相同。
  • 在抱怨性能之前,请先更正您的问题。
猜你喜欢
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 2017-08-24
  • 1970-01-01
相关资源
最近更新 更多