代码之家  ›  专栏  ›  技术社区  ›  chiborg Alessandro Minoccheri

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

  •  2
  • chiborg Alessandro Minoccheri  · 技术社区  · 14 年前

    我有两个表,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 回复  |  直到 14 年前
        1
  •  1
  •   van    14 年前

    考虑到数据,没有捷径可走。实际上这是唯一 固体 做这件事的方法。您可能需要注意的一件事是在可为空的列中正确比较空值。查询 OR 往往是缓慢的,如果是在30列就不提了。

    此外,查询将不包括 table_b 没有相应的 table_a . 所以理想情况下你会用 FULL JOIN .

    如果需要经常执行此操作,则可以引入某种附加数据列,当行中的任何内容发生更改时,这些列将始终更新。这可以简单到 TIMESTAMP 在帮助下更新的列 UPDATE/INSERT 触发器。然后当你比较时,你甚至知道哪个记录是最近的。但同样,这不是一个防弹的解决方案。

        2
  •  1
  •   Larry Lustig    14 年前

    有一种标准的sql方法可以做到这一点(减选择),但是mysql(以及许多其他dbms)不支持它。

    如果失败,您可以尝试:

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

    根据mysql文档,一个自然连接将连接所有同名列上的两个表。通过过滤掉b主键列返回空值的a记录,您实际上只得到没有匹配b表记录的a记录。

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

        3
  •  0
  •   Zak    14 年前

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