Mysql:从一个表中选择不在另一个表中的行

Posted

技术标签:

【中文标题】Mysql:从一个表中选择不在另一个表中的行【英文标题】:Mysql: Select rows from a table that are not in another 【发布时间】:2012-07-30 20:09:49 【问题描述】:

如何选择一个表中没有出现在另一个表中的所有行?

表1:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

表2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
+-----------+----------+------------+

Table1 中不在 Table2 中的行的示例输出:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

也许这样的事情应该可行:

SELECT * FROM Table1 WHERE * NOT IN (SELECT * FROM Table2)

【问题讨论】:

【参考方案1】:

一个选项是

SELECT A.*
    FROM TableA as A
    LEFT JOIN TableB as B
    ON A.id = B.id
    Where B.id Is NULL

【讨论】:

【参考方案2】:
SELECT *
FROM Table1 AS a
WHERE NOT EXISTS (
  SELECT *
  FROM Table2 AS b 
  WHERE a.FirstName=b.FirstName AND a.LastName=b.Last_Name
)

EXISTS 会帮助你...

【讨论】:

很好的答案,对于大型数据集来说很经济,谢谢。 强。大型数据集的最佳答案【参考方案3】:

试试这个简单的查询。效果很好。

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);

【讨论】:

我喜欢这个,因为一个表中的列名不必与另一个表中的列名相同,它只是比较相应的值(经过测试和工作)。【参考方案4】:

这在 Oracle 中对我有用:

SELECT a.* 
    FROM tbl1 a 
MINUS 
SELECT b.* 
    FROM tbl2 b;

【讨论】:

问题是关于 mysql 的。【参考方案5】:
SELECT a.* FROM 
FROM tbl_1 a
MINUS
SELECT b.* FROM 
FROM tbl_2 b

【讨论】:

【参考方案6】:

试试:

SELECT * FROM table1
    LEFT OUTER JOIN table2
    ON table1.FirstName = table2.FirstName and table1.LastName=table2.LastName
    WHERE table2.BirthDate IS NULL

【讨论】:

【参考方案7】:

如果您在另一条评论中提到有 300 列,并且您想要比较所有列(假设这些列都同名),您可以使用 NATURAL LEFT JOIN 隐式连接所有匹配的列名这两个表,这样您就不必繁琐地手动输入所有连接条件:

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL

【讨论】:

请注意,这仅在没有任何列具有 NULL 值时按预期工作。在 MySQL NULL != NULL 中,即使第二个表中有重复行,也会返回具有 NULL 值的每一行。 如果你有 300 列,你应该重新设计你的数据库。 嘿,这对我也有用,谢谢!但是如果像你上面提到的那样行数 > 300,那会是个问题吗? 我仍然对查询 btw 感到困惑。例如,如果我将“b.FirstName 为空”更改为“b.LastName 为空”会怎样?有什么不同?很抱歉问这个问题,我还是 sql 新手:D【参考方案8】:

标准的 LEFT JOIN 可以解决问题,如果加入的字段被索引, 也应该更快

SELECT *
FROM Table1 as t1 LEFT JOIN Table2 as t2 
ON t1.FirstName = t2.FirstName AND t1.LastName=t2.LastName
WHERE t2.BirthDate Is Null

【讨论】:

好吧,我想一定是这样,顺便说一句,为什么WHERE t2.Birthdate Is Null 而不是AND t1.Birthdate = t2.Birthdate 因为如果你添加它,那么每一行都会被返回,你说在输出中应该只出现不在第二个表中的行 这是一个了不起的答案,因为它不需要返回Table2的所有行! 我同意,很好的答案。我在 4 个表之间有一个多人表,将 AND 放在内部连接中肯定会更经济。【参考方案9】:

您需要根据列名进行子选择,而不是*

例如,如果您有两个表共有的 id 字段,您可以这样做:

SELECT * FROM Table1 WHERE id NOT IN (SELECT id FROM Table2)

有关更多示例,请参阅MySQL subquery syntax。

【讨论】:

感谢您的澄清!但我真的不需要根据任何字段来选择行,因为我对行中任何字段的任何变体都感兴趣...... 如果只有几列要比较,您可以按照@Steve 的示例进行连接。如果您实际上要求对具有许多列的两个表中的数据进行一般比较,您可能需要查找MySQL diff tool。 请注意,如果您在 Table2 中查看的列包含空值,这将始终返回一个空集。如果您基于主键执行此操作,则不是问题,但与尝试在其他上下文中使用此查询的人相关。 但是如果我们谈论的是大数据呢?而Table2包含100M行,例如? 聪明而聪明的回答。谢谢老哥

以上是关于Mysql:从一个表中选择不在另一个表中的行的主要内容,如果未能解决你的问题,请参考以下文章

SQL删除不在另一个表中的行

MySQL - 如何选择表中的行,其中 id 值位于另一个表中的逗号分隔字段中?

mysql - 如果不在另一个表中,则从一个表中选择,否则从另一个表中选择

从表中选择行,其中具有相同 id 的另一个表中的行在另一列中具有特定值

从表中选择字段,其中 id 不在 mysql 的另一个表中 [不工作]

根据另一个表中的列值选择一个表中的行?