2012-03-20 68 views
1

我有一个3列的表:iddatename。我正在寻找的是删除具有重复名称的记录。该规则应该保留具有最早日期的记录。例如在下面的例子中,有3个记录名为Paul。所以我想保留一个最早的日期(id=1),并删除所有其他的(id = 4 and 6)。我知道如何进行插入,更新等查询,但在这里我看不到如何使这个技巧工作。PHP SQL - 高级删除查询

id, date, name 

1, 2012-03-10, Paul 
2, 2012-03-10, James 
4, 2012-03-12, Paul 
5, 2012-03-11, Ricardo 
6, 2012-03-13, Paul 

mysql_query(?);

回答

1

我可以给你的最好建议是name上创建一个唯一索引并避免所有的麻烦。

按照以下步骤为Peter Kiss 2至3说那么做到这一点

ALTER Table tablename ADD UNIQUE INDEX name (name) 

然后按照4 Insert everything from the temporary table to the original

所有新的重复行,将被省略

+0

Hello Starx。刚好有时间来测试你今天早上提出的建议。我喜欢它,因为它很简单。问题是,在运行插入查询时,是否有办法知道该记录是否已被插入,因为表中已存在该值。我试过mysql_error,但没有检索到这种情况... – Marc 2012-03-26 09:55:28

+0

@Marc,你可以检查mysql的[insert on duplicate](http://dev.mysql.com/doc/refman/5.0/en/insert-on- duplicate.html) – Starx 2012-03-26 10:10:32

1
  1. 选择你要保留的记录
  2. 插入他们到一个临时表
  3. 从原始表中删除所有内容
  4. 从临时表中插入一切原来的
+0

你好彼得?谢谢回复。您如何看待pritaeas提出的解决方案? – Marc 2012-03-20 10:24:54

+0

该方法很好,解决方案不是。首先,你必须用ORDER BY子句创建一个查询,然后你可以有一个SELECT GROUP BY语句:SELECT'id' FROM(SELECT'id','name' FROM'table' ORDER BY'date')GROUP按'name'。在这种情况下,GROUp BY将保留结果集中最旧的行。 – 2012-03-20 10:54:01

1

像这样的工作:

DELETE FROM tablename WHERE id NOT IN (
    SELECT tablename.id FROM (
     SELECT MIN(date) as dateCol, name FROM tablename GROUP BY name /*select the minimum date and name, for each name*/ 
    ) as MyInnerQuery 
    INNER JOIN tablename on MyInnerQuery.dateCol = tablename.date 
     and MyInnerQuery.name = tablename.name /*select the id joined on the minimum date and the name*/ 
) /*Delete everything which isn't in the list of ids which are the minimum date fore each name*/ 
+0

你好马特。谢谢。我需要一点时间来测试一下......我会回来 – Marc 2012-03-20 10:28:36

+0

马特你好。今天早上有时间测试这个,很不幸的是没有工作。尽管如此,我得到你的解决方案的逻辑,但不明白为什么它不工作.... – Marc 2012-03-26 09:26:12

1

就像Matt,但没有加入:

DELETE FROM `table` WHERE `id` NOT IN (
    SELECT `id` FROM (
     SELECT `id` FROM `table` GROUP BY `name` ORDER BY `date` 
    ) as A 
) 

没有第一选择将得到“你不能在FROM子句中指定目标表'表'进行更新”

+0

你好pritaeas。感谢您试图帮助我。 'A'是什么意思? – Marc 2012-03-20 10:25:31

+0

@Marc A是内部查询的名称 – 2012-03-20 10:29:00

+0

@pritaeas当然,这将返回所有ID(因此删除没有),你需要一个顶部1或类似的不是吗? – 2012-03-20 10:29:41

0
DELETE t 
FROM tableX AS t 
    LEFT JOIN 
    (SELECT name 
      , MIN(date) AS first_date 
     FROM tableX 
     GROUP BY name 
    ) AS grp 
    ON grp.name = t.name 
    AND grp.first_date = t.date 
WHERE 
    grp.name IS NULL 
0
DELETE FROM thetable tt 
WHERE EXISTS (
    SELECT * 
    FROM thetable tx 
    WHERE tx.thename = tt.thename 
    AND tx.thedate > tt. thedate 
    ); 

(请注意,“日期”是SQL中储库字(型)“和”名称是保留字在某些SQL实现)