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

时间:2010-11-02 08:47:50

标签: sql foreign-keys

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

我正在尝试在这些列上添加FK约束,但我发现,因为表中的错误数据已经完全加载了之前已经被天真校正的错误,我需要找到哪些行不匹配另一个表然后删除它们。

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

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

11 个答案:

答案 0 :(得分:494)

这是一个简单的查询:

SELECT t1.ID
FROM Table1 t1
    LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL

关键点是:

  1. LEFT JOIN被使用;这将返回Table1中的所有行,无论Table2中是否存在匹配的行。

  2. WHERE t2.ID IS NULL条款;这会将返回的结果限制为仅从Table2返回的ID为空的行 - 换句话说,Table2中的{strong> NO 记录来自Table1的特定ID 1}}。对于Table2.IDTable1未匹配ID的所有记录,Table2将返回NULL。

答案 1 :(得分:59)

我会使用EXISTS表达式,因为它更强大,你可以更精确地选择你想要加入的行,如果是LEFT JOIN你必须把连接表中的所有东西都拿走。它的效率可能与使用null测试的LEFT JOIN的情况相同。

SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)

答案 2 :(得分:10)

SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)

表1中有一列要添加外键约束,但foreign_key_id_column中的值并不都与表2中的id匹配。

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

答案 3 :(得分:7)

T2是您要添加约束的表:

SELECT *
FROM T2
WHERE constrained_field NOT
IN (
    SELECT DISTINCT t.constrained_field
    FROM T2 
    INNER JOIN T1 t
    USING ( constrained_field )
)

删除结果。

答案 4 :(得分:3)

让我们有以下2个表(薪水和员工) enter image description here

现在我希望员工表中那些不在薪水中的记录。 我们可以用3种方式做到这一点 -

  1. 使用内部联接

    从id不在的员工中选择*(在e.id = s.id上选择员工e内联合薪资的e.id)

  2. enter image description here

    1. 使用左外连接

      从e.id = s.id中的员工e左外联接薪水中选择*,其中s.id为空

    2. enter image description here

      1. 使用完全加入

        从e.id = s.id中的员工e全外联合薪资中选择*,其中e.id不在(从工资中选择id)

      2. enter image description here

答案 5 :(得分:1)

从这里类似的问题MySQL Inner Join Query To Get Records Not Present in Other Table,我开始尝试

SELECT * FROM bigtable 
LEFT JOIN smalltable ON bigtable.id = smalltable.id 
WHERE smalltable.id IS NULL

smalltable是您缺少记录的地方,bigtable是您有所有记录的地方。该查询列出了smalltable中不存在但在bigtable上存在的所有记录。您可以用任何其他匹配条件替换id

答案 6 :(得分:0)

我不知道哪一个是优化的(与@AdaTheDev相比 )但是当我使用(至少对我来说)时,这个似乎更快

SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2

如果您想获得任何其他特定属性,可以使用:

SELECT COUNT(*) FROM table_1 where id in (SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2);

答案 7 :(得分:0)

您可以选择观看次数,如下所示:

CREATE VIEW AuthorizedUserProjectView AS select t1.username as username, t1.email as useremail, p.id as projectid, 
(select m.role from userproject m where m.projectid = p.id and m.userid = t1.id) as role 
FROM authorizeduser as t1, project as p

,然后在视图上进行选择或更新:

select * from AuthorizedUserProjectView where projectid = 49

产生如下图所示的结果,即,对于不匹配的列null已被填充。

[Result of select on the view][1]

答案 8 :(得分:-1)

SELECT * FROM First_table 减去 选择*从另一个

答案 9 :(得分:-2)

您可以执行类似的操作

   SELECT IFNULL(`price`.`fPrice`,100) as fPrice,product.ProductId,ProductName 
          FROM `products` left join `price` ON 
          price.ProductId=product.ProductId AND (GeoFancingId=1 OR GeoFancingId 
          IS NULL) WHERE Status="Active" AND Delete="No"

答案 10 :(得分:-5)

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


    select * from [dbo].[EmppDetails] e
     right join [Employee].[Gender] d on e.Gid=d.Gid
    where e.Gid is Null

    union 
    select * from [dbo].[EmppDetails] e
     left join [Employee].[Gender] d on e.Gid=d.Gid
    where d.Gid is Null