2012-03-20 65 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實現)