我需要做一些我描述为"反向加入" - 也就是说,我需要在表A中创建一个不在表B中的行列表,其中A.FNAME像B.FNAME和A.LNAME,如B.LNAME。关键是提取在先前邮件中被忽略的邮件列表条目。不幸的是,两个表之间的主键不一致。由于缺乏经验的操作员,表B在最初创建时无法从表A中复制它们。
没有为"反向加入"返回的搜索响应似乎解决了这种情况;我是否想要证明是消极的"这里?我以为我可以创建一个完整邮件列表的临时表,然后从它中删除每个在较短列表中有匹配的FNAME和LNAME的行,但我似乎无法在不破坏较短列表的情况下执行此操作。过程
答案 0 :(得分:0)
不需要加入:
SELECT *
FROM tableA
WHERE (fname, lname) NOT IN (SELECT fname, lname FROM tableB)
但可以用一个完成:
SELECT a.*
FROM tableA AS s
LEFT JOIN tableB as b ON a.fname = b.fname AND a.lname = b.lname
WHERE b.somefield_that_cannot_be_null IS NULL
第二个版本通常是我的第一直觉(加入时我的索引运气更好)但由于涉及的字段不太可能被编入索引,而且字符串比较无论如何相对昂贵,我认为第一个版本的意图是更加清晰。
注意:LIKE
是不必要的,除非您期望字段值中的通配符(%)...在这种情况下,连接版本是这两者中唯一的选项。
答案 1 :(得分:0)
您也可以使用OnOpenedListener
条款来实现这一点,即。
NOT EXISTS
如果您需要,此方法还允许您使用SELECT *
FROM tableA AS A
WHERE NOT EXISTS (SELECT * FROM tableB AS B WHERE A.FNAME LIKE B.FNAME AND A.LNAME LIKE B.LNAME)
进行比较,但我怀疑您确实想要=。
答案 2 :(得分:0)
正如Uueerdo所示,使用反连接模式。
SELECT a.*
FROM `table A` a
LEFT
JOIN `table B` b
ON b.fname = a.fname
AND b.lname = a.lname
WHERE b.fname IS NULL
让我们稍微打破一下。
它是一个外部联接,用于返回A
中的所有行以及来自B
的匹配行,其中包含WHERE
子句中的条件。< / p>
我们在table B
找到匹配项的任何行,我们保证b.fname
和b.lname
都是非空的。 (如果其中一列为NULL,则连接谓词中的相等条件不会被满足,而B中的行也不会匹配。
来自A
的{{1}}中未找到匹配项的任何行都将为B
中的所有列提供NULL值。如果我们排除B
中保证为非NULL的任何列中具有非NULL值的所有行,那么我们剩下的是来自B
的行没有的行A
中的匹配。
反连接是我们的SQL工具带中非常有用的模式。
使用B
模式可以获得等效结果。
(见尼克的答案,以示例。)
奇怪的是,在MySQL 5.6中,有适当的索引可用于&#34; 反连接&#34;查询模式,EXPLAIN输出实际显示&#34; 不存在&#34;。
NOT EXISTS
对于等效的&#34; 不存在&#34;查询时,EXPLAIN输出略有不同,显示了一个从属子查询。
-- explain antijoin
id select_type table type key rows Extra
-- ------------------ ----- ---- ---- ------ ------------------------------------
1 SIMPLE a ALL 210339
1 SIMPLE b ref FK_a 1 Using where; Not exists; Using index
就个人而言,我选择反加入,因为我倾向于看到最好的表现。 (-- explain "not exists" equivalent
id select_type table type key rows Extra
-- ------------------ ----- ---- ---- ------ ------------------------------------
1 PRIMARY a ALL 210339 Using where
2 DEPENDENT SUBQUERY b ref FK_a 1 Using index
模式可能会提供更好的效果,NOT EXISTS
我们不太可能看到更好的效果。