用于查找ID不在另一个表中的记录的SQL查询

时间:2012-08-21 04:57:13

标签: sql database postgresql

我在数据库中有两个带有绑定主键的表,我希望在它们之间找到一个不相交的集合。例如,

  • Table1包含列(ID, Name)和示例数据:(1 ,John), (2, Peter), (3, Mary)
  • Table2包含列(ID, Address)和示例数据:(1, address2), (2, address2)

那么我该如何创建一个SQL查询,以便我可以获取table1中不在table2中的ID的行。在这种情况下,应该返回(3, Mary)

Ps。 ID是这两个表的主键。

提前致谢。

6 个答案:

答案 0 :(得分:163)

试试这个

SELECT ID, Name 
FROM   Table1 
WHERE  ID NOT IN (SELECT ID FROM Table2)

答案 1 :(得分:73)

使用LEFT JOIN

SELECT  a.*
FROM    table1 a
            LEFT JOIN table2 b
                on a.ID = b.ID
WHERE   b.id IS NULL

答案 2 :(得分:8)

快速替代

我运行了一些测试(在postgres 9.5上),使用两个表,每个表约2M行。下面的查询比其他提出的查询执行了至少5 *:

-- Count
SELECT count(*) FROM (
    (SELECT id FROM table1) EXCEPT (SELECT id FROM table2)
) t1_not_in_t2;

-- Get full row
SELECT table1.* FROM (
    (SELECT id FROM table1) EXCEPT (SELECT id FROM table2)
) t1_not_in_t2 JOIN table1 ON t1_not_in_t2.id=table1.id;

答案 3 :(得分:5)

请记住上面@John Woo的评论/链接中的观点,这就是我通常会处理它的方式:

SELECT t1.ID, t1.Name 
FROM   Table1 t1
WHERE  NOT EXISTS (
    SELECT TOP 1 NULL
    FROM Table2 t2
    WHERE t1.ID = t2.ID
)

答案 4 :(得分:3)

基本上有3种方法可以使用:not existsnot inleft join / is null

具有IS NULL的左联接

SELECT  l.*
FROM    t_left l
LEFT JOIN
        t_right r
ON      r.value = l.value
WHERE   r.value IS NULL

禁止进入

SELECT  l.*
FROM    t_left l
WHERE   l.value NOT IN
        (
        SELECT  value
        FROM    t_right r
        )

不存在

SELECT  l.*
FROM    t_left l
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    t_right r
        WHERE   r.value = l.value
        )

哪个更好?最好将这个问题的答案分解成主要的特定RDBMS供应商。一般来说,当子查询中的记录数量未知时,应避免使用select ... where ... in (select...)。一些供应商可能会限制大小。例如,Oracle有一个limit of 1,000。最好的办法是尝试所有这三个步骤并显示执行计划。

特定于PostgreSQL,NOT EXISTSLEFT JOIN / IS NULL的执行计划是相同的。我个人更喜欢NOT EXISTS选项,因为它显示了更好的意图。毕竟,语义是您要在A中查找其pk 不存在在B 中的记录。

旧的但仍然是黄金,尽管特定于PostgreSQL:https://explainextended.com/2009/09/16/not-in-vs-not-exists-vs-left-join-is-null-postgresql/

答案 5 :(得分:1)

SELECT COUNT(ID) FROM tblA a
WHERE a.ID NOT IN (SELECT b.ID FROM tblB b)    --For count


SELECT ID FROM tblA a
WHERE a.ID NOT IN (SELECT b.ID FROM tblB b)    --For results