我有一个MySQL(5.4)表,其中有一些行有重复的字段(有时2-5个副本),我想删除,只留下一个。但它并不像选择最高或最低ID一样简单。我要删除的重复项是那些在另一个表格中没有相应条目的重复项。
表tb_email_to_members
包含email_id
(自动递增)和email_address
(以及其他相关的字段)。例如:
email_id email_address
-------------------------
1 arnold@foo.com
2 foo@foo.com
3 foo@foo.com
4 foo@foo.com
5 jeanluc@foo.com
表格tb_tx
包含tx_id
(自动递增)和frn_email_id
(以及其他不相关的字段),其中tb_tx.frn_email_id
与{tb_email_to_members.email_id
匹配1}}。例如:
tx_id frn_email_id
--------------------------
100 5
101 2
102 19
103 19
104 19
105 1
我希望在email_address
中删除tb_email_to_members
重复一次或多次的行,但仅限于frn_email_id
中tb_tx
中没有包含email_id
的行的tb_email_to_members
1}}来自tb_tx
。我需要确保留下一行重复项,即使它们都没有tb_email_to_members
中的相应条目。在上面的示例中,我想从tb_tx
中删除第3行和第4行,因为tb_email_to_members
中只存在第2行。
(实质上,tb_tx
将电子邮件地址映射到另一个表中的用户帐户,tb_email_to_members
将订单映射到tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#FFFFFF"));
的电子邮件地址。)
我可以很容易地找到重复项,并且我看到很多用于删除重复项的代码,但没有根据需要根据另一个表的查找失败而仅删除某些重复项的调整。建议?
答案 0 :(得分:0)
这应该回答你的问题:
DELETE FROM tb_email_to_members WHERE email_id NOT IN (select frn_email_id FROM tb_tx);
答案 1 :(得分:0)
我认为,这正是你想要的。它仅删除tb_email_to_members中的重复条目,其中tb_tx中没有相关行,并保留所有原始文件。
请注意,您没有说明如何从tb_tx中删除条目,因此该表中的重复项将保持不变(在示例内容中,行102-104)。
我在这里使用的方法基本上是伪代码:
DELETE FROM表WHERE id_col IN( SUBQUERY选择一个id列并应用WHERE过滤器,确保每个id NOT in( 另一个SUBQUERY只选择每个分组中的第一个项目,与第一个SUBQUERY非常相似 ) )
那里有另一个SUBQUERY(第2行)包装整个事物,这可以防止MySQL抱怨你不能同时选择和修改表。
注意:如果您的数据集很大,这可能会很慢。在手动删除大量数据之前备份表格!
我意识到这是一个相当复杂的查询,但确实有效。
DELETE FROM tb_email_to_members WHERE email_id IN (
SELECT * FROM (
SELECT ids.eid FROM (
SELECT tb_email_to_members.email_id AS eid, dup.email_id AS eid2, dup.email_address, frn_email_id
FROM tb_email_to_members
LEFT JOIN (
SELECT email_id, email_address FROM tb_email_to_members
GROUP BY email_address
HAVING count(email_id) > 1) AS dup
ON tb_email_to_members.email_address = dup.email_address
INNER JOIN tb_tx tx ON dup.email_id = tx.frn_email_id
) AS ids
WHERE ids.eid NOT IN (
SELECT tb_email_to_members.email_id AS eid FROM tb_email_to_members
LEFT JOIN (
SELECT email_id, email_address FROM tb_email_to_members
GROUP BY email_address
HAVING count(email_id) > 1) AS dup
ON tb_email_to_members.email_address = dup.email_address
INNER JOIN tb_tx tx ON dup.email_id = tx.frn_email_id
GROUP BY dup.email_id
)
) AS foo
)
答案 2 :(得分:0)
tb_email_to_members
中存在一次
DELETE FROM tb_email_to_members
WHERE email_id NOT IN (SELECT frn_email_id FROM tb_tx)
AND email_address IN (SELECT email_address FROM tb_email_to_members GROUP BY email_address HAVING COUNT(email_address) > 1);
显然,将DELETE
更改为SELECT *
会向您显示您将要删除的内容。
了解tb
的加分点是花絮的简称?