确定。请耐心等待我解释。
我有一个通过网站上的表单收集的联系信息数据库。显然,人们不小心按下提交不止一次(或故意,但修复是一个不同的问题)所以这个数据库中有很多重复的行。
因此,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为每个人保留多个值。这就是表的结构(表2中有大约一百万行,所以我现在不想改变结构。)
所以我的困境是这样的:我知道创建临时表和SELECT DISTINCT(所有字段)很容易,但我想保留至少1个重复行的唯一ID字段。如果我保留唯一ID字段,它对每一行都是唯一的,即使其他数据完全相同,因此SELECT DISTINCT(所有字段)将不起作用,它将保留每一行。希望我彻底解释了这一点。如果需要,请向我询问更多信息。
编辑:我确信我可以摆脱每张桌子的ID字段,但就我而言,它只是......它就在那里。
答案 0 :(得分:1)
通过第一次澄清和线条之间的一点阅读,我们可以猜测,只保留表1中给定“唯一ID代码”的第一个或最后一个条目,其中第一个或最后一个表示最旧或最新条目。除了MAX和MIN之外,查询是相同的。我假设“日期”列包含足够精细(1秒或更小)的粒度,在时间量上你没有得到两次相同的唯一ID码;如果“日期”列实际上只包含DATE(年,月,日)值,则情况不太可能如此,但如果您有TIMESTAMP(3)可能就是这种情况,TIMESTAMP可能就是这种情况。 / p>
与SQL一样,分阶段构建查询,很好,轻柔。
SELECT Unique_ID_Code, MAX(date) AS Newest
FROM Table1
GROUP BY Unique_ID_Code
HAVING COUNT(*) > 1
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。
尝试使用生产数据库的副本。
答案 1 :(得分:0)
这将更新表2以使用相同联系信息的最低唯一ID号:
UPDATE Table2 SET Table2.uniqueID = ( SELECT T1.UniqueID FROM Table1 T1, Table1 T2 WHERE T1.unique ID < T2.unique ID AND T1.firstname = T2.firstname AND T1.date = T2.date AND T1.blah, blah = T2.blah, blah ) WHERE Table2.uniqueID = ( Select T1.UniqueID from Table1 T1, CopyOfTable1 T2 where T1.firstname = T2.firstname and T1.date = T2.date and T1.blah, blah = T2.blah, blah );
这将删除除ONE之外的所有(具有最低的uniqueID)重复的联系信息记录:
delete T1 from Table1 T1, CopyOfTable1 T2 where T1.unique ID > T2.unique ID and T1.firstname = T2.firstname and T1.date = T2.date and T1.blah, blah = T2.blah, blah