2012-02-01 72 views
0

我希望能在一個MySQL數據庫表的重複記錄的金額限制爲2SQL中刪除所有,但2複製

(不含id領域是自動遞增)

我的表設置如

id city  item 
--------------------- 
1  Miami  4 
2  Detroit 5 
3  Miami  4 
4  Miami  18 
5  Miami  4 

所以在該表中,只有第5行將被刪除。

我該怎麼做?

+2

爲什麼允許任何重複記錄? – Bernard 2012-02-01 20:17:42

+0

恐怕你將不得不使用某種腳本\ pl-sql與循環。 – gdoron 2012-02-01 20:18:29

回答

1

我覺得這裏的問題是,無論你的代碼和/或表結構允許插入重複,你是問這個問題的時候,你應該真正解決您的數據庫和/或代碼。

3

當讀寫同一張表時,MySQL有一些缺陷。所以,我真的不知道這是否會工作,語法是SQL的許多實現很好,但我不知道這是否是MySQL的友好...

DELETE 
    yourTable 
WHERE 
    1 < (SELECT COUNT(*) 
     FROM yourTable as Lookup 
     WHERE city = yourTable.city AND item = yourTable.item AND id < yourTable.id) 

編輯

令人驚訝錯綜複雜,但值得一試?

DELETE 
    yourTable 
FROM 
    yourTable 
INNER JOIN 
(
    SELECT 
    id 
    FROM 
    (
    SELECT 
     id 
    FROM 
     yourTable 
    WHERE 
     1 < (SELECT COUNT(*) 
      FROM yourTable as Lookup 
      WHERE city = yourTable.city AND item = yourTable.item AND id < yourTable.id) 
) 
    AS inner_deletes 
) 
    AS deletes 
    ON deletes.id = yourTable.id 
+0

雖然這會刪除所有符合條件的記錄。所以如果一個特定項目有4個發生,**所有**將被刪除。 – Yuck 2012-02-01 20:24:37

+0

@yuck - 否,'ID MatBailie 2012-02-01 20:28:30

+0

+1你可以編輯這個解釋到你的答案中,因爲我認爲這非常有幫助。 – Yuck 2012-02-01 20:30:47

0

我認爲更好的辦法是避免讓超過5個寄存器,你必須實現驗證,其中如果SELECT COUNT(*)> 3,你將不接受新的插入。

,因爲如果你想要做的到數據層這一點,你必須使用一個存儲過程,因爲首先你需要找出所有的寄存器有3級以上的寄存器和刪除只有最後一個。 Saludos

+0

你假設OP可以控制應用程序。也許這是*的情況,但問題是嚴格的清理數據。 – Yuck 2012-02-01 20:42:14

0

由於MySQL在更新查詢表時非常困難(例如,請參閱Dems的答案),我可以發現的最好的結果不止是一個語句,而是在正面可讀性上;

CREATE TEMPORARY TABLE Dump AS SELECT id FROM table1 WHERE id NOT IN 
    (SELECT MIN(id) FROM table1 GROUP BY city,item UNION 
    SELECT MAX(id) FROM table1 GROUP BY city,item); 

DELETE FROM table1 where id in (select * from Dump); 

DROP TABLE DUMP; 

不知道是否重要哪個重複被刪除,這會保持第一個和最後一個。

+0

有沒有簡單的方法讓它保存說,3行或5? – user1022585 2012-02-01 21:58:04

0

在你回答Joachim的回答時,你問到保存3或5行,這是完成它的一種方法。根據你如何使用這個數據庫,你可以在一個循環中調用它,或者你可以把它變成一個存儲過程。無論哪種方式,您都會繼續運行這整塊代碼,直到受影響的行數爲0:

drop table if exists TempTable; 
create table TempTable 
select city, item, 
     count(*) as record_count, 
     min(id) as ItemToDrop -- this could be changed to max() if you 
          -- want to delete new stuff instead 
from YourTable 
group by city, item 
having count(*) > 2; -- This value = number of rows you save 

delete from YourTable 
where id in (select ItemToDrop from TempTable);