从表 A 中获取不在表 B 中的记录

Posted

技术标签:

【中文标题】从表 A 中获取不在表 B 中的记录【英文标题】:Get records from Table A, that are not in Table B 【发布时间】:2013-05-26 12:04:18 【问题描述】:

我是 SQL 新手,还不能正确获取此 SQL 查询。我目前有:

SELECT * FROM tableA
LEFT OUTER JOIN tableB
ON tableA.`full_name` = tableB.`full_name`
WHERE tableB.`id` IS NULL

两张表都有人员记录,包括姓名和地址。我需要获取 tableA 中的所有记录,而不是 tableB。下图基本就是我需要的:

问题是两个人可能有相同的名字,但不同的地址。所以最终,我需要获取 tableA 中所有人员的记录,不包括具有重复名称和地址的重复项。

每个表都有如下列:

id,full_name,first_name,last_name,title,phone,address,city,state,postal_code

【问题讨论】:

你能显示表格的结构,这样我们就不用猜名字了吗? :) 大声笑,是的。好主意。 :) 我会编辑问题。 您是说您需要 DISTINCT 名称和地址组合吗?还是您需要为拥有多个地址的人选择一个地址? 我需要 DISTINCT 名称和地址组合。 EX:可能有两个人的名字相同,但我们知道他们是不同的人,因为他们有不同的地址。所以,我需要保留那些可能名称相同但地址不同的人。 【参考方案1】:

以下查询将根据全名和地址为您提供 tableA 中不在 tableB 中的所有人员的 id:

SELECT tableA.id FROM tableA
LEFT OUTER JOIN tableB
-- people are the same if fullname and adress match
ON tableA.`full_name` = tableB.`full_name`
   AND tableA.adress = tableB.adress
-- filter people that re in tableA only
WHERE tableB.`id` IS NULL
-- filter duplicates
GROUP BY tableA.id

您可以轻松地编辑此选择以包含您需要的来自 tableA 的任何信息。

【讨论】:

【参考方案2】:

你检查过这个优秀的页面吗? http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.name WHERE TableB.id IS null

【讨论】:

这是我最初拥有的东西的地方 - 但它并没有解决我的问题,即人们拥有相同的名字,但不同的地址。 哈哈是的。该图像有助于绘制我需要的图表 - 在大多数情况下。【参考方案3】:

由于您要加入两个字段,因此您可以选择 ANTI-JOIN (Friederike S' answer) Not exists

SELECT DISTINCT tablea.* 
FROM   tablea 
WHERE  NOT EXISTS (SELECT * 
                   FROM   tableb 
                   WHERE  tablea.`full_name` = tableb.`full_name`
                          AND tableA.adress = tableB.adress) 

DEMO

你也可以用not in见(Christian Ammer's)回答

另一个更模糊的解决方案是使用ALL 关键字。和NOT IN很像

SELECT DISTINCT tablea.* 
FROM   tablea 
WHERE 

( tablea.`full_name`  , tableA.address) 

  !=  ALL (SELECT tableb.`full_name`, tableB.address 
           FROM tableb)

DEMO

【讨论】:

您的答案也很有效,但选择了 Friederike 的答案,因为它是第一个。谢谢 @mdance 一个额外的注释。根据所涉及的列的可空性,您将获得两者之间的不同性能特征。见Quassnoi的文章LEFT JOIN / IS NULL vs. NOT IN vs. NOT EXISTS: nullable columns 另一个选项是 NOT IN(参见my answer),它不需要像 NOT EXISTS 选项那样的相关子查询。 @ChristianAmmer 谢谢我完全忘记了 mysql 的 IN 奇怪,所以我更新了我的答案。但是,您应该小心出于性能原因避免相关子查询的含义。正如 Quassanoi 的文章所指出的,所涉及领域的 Nullablitiy 决定了您应该使用哪种解决方案。 MySQL 没有任何奇怪之处(至少在这种情况下没有),您可以包含多于一列的子查询(标准说,您可以使用 Mimer SQL-92 validator 检查它)跨度> 【参考方案4】:

您可以使用 NOT EXIST 子句。此条件将返回 tableA 中没有给定 full_name 的 tableB 记录的所有记录。

   SELECT * FROM 
   tableA
   WHERE 
   NOT EXISTS (select * from tableB Where tableA.full_name = tableB.full_name);

【讨论】:

【参考方案5】:

在我看来,用子查询而不是 JOIN 编写这样的查询是合乎逻辑的。而且因为它是一个不相关的子查询,所以与 JOIN 版本应该没有性能差异。

SELECT *
FROM tableA
WHERE (full_name, address) NOT IN
(SELECT full_name, address FROM tableB);

您可以在SQL Fiddle 上查看结果。

也看看这个答案:

Sub-queries are the logically correct way to solve problems of the form, "Get facts from A, conditional on facts from B" A non-correlated subquery (one in which the where condition is independent of the containing query) will execute once at the beginning.

【讨论】:

以上是关于从表 A 中获取不在表 B 中的记录的主要内容,如果未能解决你的问题,请参考以下文章

如果表 A 中的值不为空,我如何从表 B 中获取值

从表 A 中选择与表 B 中的两列匹配的记录子集

如果存在表 B,则从表 B 中获取数据,否则保留表 A(在某些列之后)

如何从表 A 中选择表 B 中不存在的记录 [重复]

SQL中,如何查询存在一个表而不在另一个表中的数据记录

Spark SQL 中的 where 子句与 join 子句