如何比较两列以在MySQL中找到不匹配的记录

时间:2011-10-02 18:25:21

标签: mysql

我有一个包含2列的MySQL表,每列有数千条记录

对于示例15000第1列中的电子邮件地址和第2列中的15005电子邮件地址

如何从15005中找到在column1中无法匹配的那5条记录?

我希望MySql查询比较两个列并仅给出5个不匹配记录的结果

谢谢

2 个答案:

答案 0 :(得分:16)

不确定我是否正确......但它会是什么样的?

select column2 from table
where column2 not in (select column1 from table)

答案 1 :(得分:8)

理查德,从表中的一列中找到匹配/缺少的行与同一表中的另一列相比,这是非常不寻常的。

您可以将表视为事实的集合,每行都是一个事实。将值转换为谓词是我们理解数据的方式。一个表中的值“12”可能表示“存在12个小部件的日期”或“1月1日12个人购买小部件”或“1月12日没有销售小部件”,但无论如何表的相应谓词是“12”应代表事实。

想要找到两个表之间的区别是很常见的:“B中哪些事实不属于A?”但是在一个包含两列的表中,每一行在概念上应该是关于这对值的事实。行(12,13)的谓词可能是“1月12日,我们卖掉了13个小部件。”但在那种情况下,我怀疑你是否会要求提供这些信息。

所以,如果(12,13)真的是两个相同的谓词 - “12区的某人购买了小部件,而且13区的某人购买了小部件” - 从长远来看,如果那些生活将更容易是一列,而不是两列。如果它是两个不同的谓词,那么它们在两个表中会更有意义。 SQL的灵活性可以处理这些情况,但您可能会在以后遇到更多问题。如果您对此主题感兴趣,搜索“规范化”会找到比您想知道的更多的方式:)

无论如何,我认为您正在寻找的查询使用LEFT JOIN来比较表格与自身。我将值1-15000添加到col1,将1-15005添加到此表中的col2:

CREATE TABLE `foo` (
  `col1` int(11) DEFAULT NULL,
  `col2` int(11) DEFAULT NULL,
  KEY `idx_col1` (`col1`),
  KEY `idx_col2` (`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

mysql> select count(distinct col1), count(distinct col2) from foo;
+----------------------+----------------------+
| count(distinct col1) | count(distinct col2) |
+----------------------+----------------------+
|                15000 |                15005 |
+----------------------+----------------------+
1 row in set (0.01 sec)

通过给同一个表两个名称,我可以将它们的两列相互比较,并找到没有相应col1值的col2值 - 在这些情况下,f1.col1将为NULL:

mysql> select f2.col2
from foo as f2 left join foo as f1 on (f2.col2=f1.col1)
where f1.col1 is null;
+-------+
| col2  |
+-------+
| 15001 |
| 15002 |
| 15003 |
| 15004 |
| 15005 |
+-------+
5 rows in set (0.03 sec)

关于莫斯蒂昨天的解决方案,我不确定这是否正确。我尽量不使用子查询,所以我在这里有点超出我的深度。但它似乎不适用于我至少尝试复制您的数据集:

mysql> select col2 from foo where col2 not in
(select col1 from foo);
Empty set (0.02 sec)

如果我从子查询中排除5个NULL,它会起作用,这告诉我“NOT IN(NULL)”不一定按照人们认为它的工作方式工作:

mysql> select col2 from foo where col2 not in
(select col1 from foo where col1 is not null);
+-------+
| col2  |
+-------+
| 15001 |
| 15002 |
| 15003 |
| 15004 |
| 15005 |
+-------+
5 rows in set (0.02 sec)

我在MySQL中避免子查询的主要原因是它们具有不可预测的性能特征,或者至少足够复杂, I 无法预测它们。有关详细信息,请参阅http://dev.mysql.com/doc/refman/5.5/en/subquery-restrictions.html中的“O(MxN)”评论以及简短网页http://dev.mysql.com/doc/refman/5.5/en/rewriting-subqueries.html上的建议。