如何在具有相同结构的两个MySQL表中选择不同的行?

时间:2010-03-16 17:25:58

标签: sql mysql diff

我有两个表A和B,它们具有相同的结构(大约30多个字段)。是否有一种简短,优雅的方式来连接这些表,只选择一列或多列不同的行?我当然可以编写一些脚本来创建包含所有列名的查询,但也许只有一个SQL解决方案。

换句话说:有一个简短的替代品:

SELECT *
FROM   table_a a
  JOIN table_b b ON a.pkey=b.pkey
WHERE  a.col1 != b.col2
    OR a.col2 != b.col2
    OR a.col3 != b.col3 # .. repeat for 30 columns

3 个答案:

答案 0 :(得分:1)

有一种标准的SQL方法(MINUS SELECT),但MySQL(以及许多其他DBMS)不支持它。

如果做不到,你可以试试这个:

SELECT a.* FROM a NATURAL LEFT JOIN b
    WHERE b.pkcol IS NULL

根据MySQL文档,NATURAL JOIN将在所有具有相同名称的列上连接两个表。通过过滤出b主键列返回NULL的记录,您实际上只获得了没有匹配的b表记录的记录。

仅供参考:这是基于MySQL文档,而不是个人经验。

答案 1 :(得分:1)

考虑到数据,没有简短的方法。实际上,这是唯一的坚实方式。您可能需要注意的一件事是在NULL-able列中正确比较NULL值。 OR的查询往往很慢,没有提及它是否在30列。

此外,您的查询不会在table_b中包含table_a中没有相应记录的记录。理想情况下,您会使用FULL JOIN

如果您需要经常执行此操作,那么您可以引入某种额外的数据列,当行中的任何内容发生更改时,该列会立即更新。这可以像TIMESTAMP列一样简单,在UPDATE/INSERT个触发器的帮助下进行更新。然后,当您进行比较时,您甚至可以了解哪个记录更新。但同样,这不是一个防弹解决方案。

答案 2 :(得分:0)

我能想到的最好的方法是创建一个具有相同结构的临时表,但在要检查的30个字段中有一个唯一的限制。然后将表A中的所有行插入临时表,然后将表B中的所有行插入临时表...当B中的行进入时,(使用insert ignore)在至少1列上不唯一的那些行将被丢弃结果是您只有行中至少有1列在您的临时表中进行分析。然后您可以从中选择所有内容。