如何在另一个表中选择没有匹配条目的行?

Fro*_*840 291 sql foreign-keys

我正在对数据库应用程序进行一些维护工作,并且我发现,欢乐的乐趣,即使来自一个表的值正在使用外键的样式,表上没有外键约束.

我正在尝试在这些列上添加FK约束,但我发现,因为表中的错误数据已经完全加载了以前的错误,这些错误已经被天真地纠正过,我需要找到没有的行.匹配其他表,然后删除它们.

我在网上找到了一些这种查询的例子,但它们似乎都提供了例子而不是解释,我不明白为什么它们起作用.

有人可以向我解释如何构建一个查询,该查询返回在另一个表中没有匹配的所有行,以及它正在做什么,以便我可以自己进行这些查询,而不是为这个混乱中的每个表运行到SO 没有FK约束?

Ada*_*Dev 549

这是一个简单的查询:

SELECT t1.ID
FROM Table1 t1
    LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL
Run Code Online (Sandbox Code Playgroud)

关键点是:

  1. LEFT JOIN用来; 这将返回所有行Table1,无论是否有匹配的行Table2.

  2. WHERE t2.ID IS NULL条款; 这会将返回的结果限制为仅返回ID的行为Table2空 - 换句话说,该特定ID中没有记录.对于未匹配ID的所有记录,将返回NULL .Table2Table1Table2.IDTable1Table2

  • @Michael - 如果你的架构中有一个"NULL"ID有效,你可能会有更大的问题,你不同意吗?:) (145认同)
  • 如果ID为NULL,则失败 (4认同)
  • 当表 1 中的每一行在表 2 中有多于一行时,这比“存在”慢得多。/sf/answers/2568613491/ 是一个更好的答案 (3认同)
  • 我觉得很奇怪,我们首先说:`t1.ID = t2.ID`,这意味着两个表中的 id 应该相等,然后我们说哦,但另一个表上的 id 应该为 null `t2.ID IS NULL ` 第二个语句是否意味着 t1.ID != t2.ID 与第一个语句矛盾? (2认同)
  • @Jas答案的关键点1,第一个表中的所有行,甚至那些不匹配左连接的 t1.ID = t2.ID 条件的行。如果将第一行更改为“SELECT t1.ID, t2.ID”并删除 WHERE 行,您将更好地了解其工作原理。 (2认同)

Ond*_*zek 79

我会使用EXISTS表达式,因为它更强大,你可以更精确地选择你想要加入的行,如果LEFT JOIN你必须采取连接表中的所有内容.它的效率可能与LEFT JOIN使用零测试的情况相同.

SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)
Run Code Online (Sandbox Code Playgroud)

  • 是的,`EXISTS`的主要优点是可变性。 (2认同)
  • 实际上,我将一个查询的速度从7秒降低到了200ms ...(与“ WHERE t2.id IS NULL”相比)谢谢。 (2认同)
  • @MotiKorets您的意思是提高了速度:) (2认同)

小智 13

SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)
Run Code Online (Sandbox Code Playgroud)

表1中有一列要添加外键约束,但foreign_key_id_column不是全部的值与id表2中的值匹配.

  1. 初始选择列出了idtable1 中的s.这些将是我们要删除的行.
  2. NOT INwhere语句中的子句将查询限制为只有其中的值foreign_key_id_column不在表2 id的列表中的行.
  3. SELECT括号中的语句将获得id表2 中所有s 的列表.


Deb*_*ash 9

让我们有以下 2 个表(薪水和员工) 在此处输入图片说明

现在我想要那些不在工资中的员工表中的记录。 我们可以通过 3 种方式做到这一点:

  1. 使用内部连接
select * from employee
where id not in(select e.id from employee e inner join salary s on e.id=s.id)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  1. 使用左外连接
select * from employee e 
left outer join salary s on e.id=s.id  where s.id is null
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  1. 使用完全连接
select * from employee e
full outer join salary s on e.id=s.id where e.id not in(select id from salary)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


小智 7

T2您要添加约束的表在哪里:

SELECT *
FROM T2
WHERE constrained_field NOT
IN (
    SELECT DISTINCT t.constrained_field
    FROM T2 
    INNER JOIN T1 t
    USING ( constrained_field )
)
Run Code Online (Sandbox Code Playgroud)

并删除结果.