我有两个表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
答案 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列在您的临时表中进行分析。然后您可以从中选择所有内容。