从表 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 中的记录的主要内容,如果未能解决你的问题,请参考以下文章