好的。请耐心听我说,我不擅长解释事情。
我有一个通过网站上的表格收集的联系信息数据库。显然,人们不小心(或故意,但修复是一个不同的问题)多次按下“提交”,因此该数据库中有很多重复的行。
因此,table1 保存联系信息,如下所示:
ID | date | unique ID code | first name, blah blah
1 stuff 20110101ba78b joe
table2 保存由唯一 ID 代码字段连接的相关数据,如下所示:
ID | data | unique ID code
1 a 20110101ba78b
2 b 20110101ba78b
因此,table2 为每个人保存了多个值。这就是表的结构(table2 中有大约一百万行,所以我现在不想更改结构)。
所以我的困境是这样的:我知道创建临时表和 SELECT DISTINCT(所有字段)很容易,但我想保留至少 1 个重复行的唯一 ID 字段。如果我保留唯一的 ID 字段,那么它对于每一行都是唯一的,即使其他数据完全相同,因此 SELECT DISTINCT(all fields) 将不起作用,它将保留每一行。希望我彻底解释了这一点。如果需要,请向我询问更多信息。
编辑:我确信我可以删除每个表的 ID 字段,但就我而言,它只是......在那里。
最佳答案
通过第一个澄清和行间的一些阅读,我们可以猜测,在表 1 中仅保留给定“唯一 ID 代码”的第一个或最后一个条目就足够了,其中第一个或最后一个表示最旧或最新入口。除了 MAX 与 MIN 之外,查询是相同的。我假设“日期”列包含足够精细(1 秒或更小)的粒度,您不会在一个时间段内两次获得相同的唯一 ID 代码;如果“日期”列实际上只包含 DATE(年、月、日)值,则不太可能出现这种情况,但如果您有 TIMESTAMP(3),则可能是这种情况,并且很可能是 TIMESTAMP 的情况。
与 SQL 一样,分阶段构建查询,良好且温和。
查找具有多个条目的每个唯一 ID 代码的最新条目
SELECT Unique_ID_Code, MAX(date) AS Newest
FROM Table1
GROUP BY Unique_ID_Code
HAVING COUNT(*) > 1
查找与最新条目匹配的唯一 ID 代码的详细信息
SELECT T1.*
FROM Table1 AS T1
JOIN (SELECT Unique_ID_Code, MAX(date) AS Newest
FROM Table1
GROUP BY Unique_ID_Code
HAVING COUNT(*) > 1
) AS M
ON M.Unique_ID_Code = T1.Unique_ID_Code AND M.Newest = T1.Date
现在是棘手的事情
您接下来要做什么取决于您对 DBMS 中事务支持的信任程度以及 Table1 有多大,以及您的外键是否有 ON DELETE CASCADE 约束,以及...
您可以使用上面第二个查询选择的行创建一个临时表(我相信是 MySQL 语法;其他 DBMS 对此使用不同的表示法)。
CREATE TEMPORARY TABLE KeepTheseRows
SELECT T1.*
FROM Table1 AS T1
JOIN (SELECT Unique_ID_Code, MAX(date) AS Newest
FROM Table1
GROUP BY Unique_ID_Code
HAVING COUNT(*) > 1
) AS M
ON M.Unique_ID_Code = T1.Unique_ID_Code AND M.Newest = T1.Date;
然后从 Table1 中删除与重复的唯一 ID 代码匹配的所有行:
DELETE FROM Table1
WHERE Unique_ID_Code IN (SELECT Unique_ID_Code FROM KeepTheseRows);
然后恢复要保留的行:
INSERT INTO Table
SELECT * FROM KeepTheseRows;
发生这种情况时,您可能需要推迟约束检查,或者可能需要在发生这种情况时删除外键约束。您需要担心此操作发生时的事件;最好不要在运行时向 Table1 中插入行。如果他们在您运行时修改表,您可能会发现必须执行多次处理。您应该尽快向 Table1.Unique_ID_Code 添加唯一约束,以免再次陷入困惑。 (并且不要忘记重新启用任何延迟约束或重新创建和删除的外键。)
可能还有其他等效的方法可以做到这一点;除了临时表表示法之外,这仅依赖于标准 (SQL-92) SQL。
使用生产数据库的副本进行实验。
关于php - 在这种(稍微)复杂的 MySQL 数据库情况下,如何删除重复行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4772586/