2012-06-08 28 views
2

我有一個約1M記錄的數據庫表。我需要在此表中找到所有重複的名稱,並使其唯一。如何將重複的行更改爲mysql中的唯一值?

例如...

Id Name 
----------- 
1 A 
2 A 
3 B 
4 C 
5 C 

應改爲...

Id Name 
----------- 
1 A-1 
2 A-2 
3 B 
4 C-1 
5 C-2 

是否與一個MySQL查詢或過程這樣做的有效途徑?

在此先感謝!

回答

2

這是一個有點棘手。我測試了我的本地主機上,它你想要做什麼..讓我知道,如果你有任何問題。 SQL FIDDLE

UPDATE temp t1, 
(
    SELECT 
     id as unique_id, 
     new_name 
    FROM(
     SELECT 
      id, 
      IF(@ROW = Name, @COUNT, @COUNT := 1), 
      CONCAT(Name, ' - ', @COUNT) AS new_name, 
      @ROW := Name, 
      @COUNT := @COUNT + 1 
     FROM temp 
     JOIN (SELECT @COUNT := 0, @ROW := "") AS t 
     WHERE Name IN(SELECT Name FROM temp 
     GROUP BY Name 
     HAVING COUNT(Name) > 1) 
    ) AS temp_test 
) as testing 
SET t1.Name = testing.new_name where t1.id = testing.unique_id 

最終輸出結果如下:PICTURE


編輯: 這可以更好地爲性能考慮

先運行此查詢

SET SESSION group_concat_max_len = 1000000; -- longer if needed 
SET @query1 := (
SELECT 
    GROUP_CONCAT(DISTINCT unique_name) 
FROM temp 
JOIN(
    select Name as unique_name 
    FROM temp 
    GROUP BY name 
    HAVING COUNT(Name) > 1 
) as t 
); 

2.然後運行此更新

UPDATE temp t1, 
(
    SELECT 
     id as unique_id, 
     new_name 
    FROM(
     SELECT 
      id, 
      IF(@ROW = Name, @COUNT, @COUNT := 1), 
      CONCAT(Name, ' - ', @COUNT) AS new_name, 
      @ROW := Name, 
      @COUNT := @COUNT + 1 
     FROM temp 
     JOIN (SELECT @COUNT := 0, @ROW := "") AS t 
     WHERE FIND_IN_SET (`name`, @query1) 
    ) AS temp_test 
) as testing 
SET t1.Name = testing.new_name where t1.id = testing.unique_id 

我測試了我的地方,它的工作原理,所以你應該能夠得到這個運行:)

+0

謝謝你,但它太痛苦了(測試沒有更新,只是選擇,10k數據集超過10分鐘),這方面還有改進的餘地嗎?還請包括「UPDATE」語法 – Sharky

+0

@Sharky對不起,我以爲我已經包含更新語法..我只是做了。從我所能想到的事情來做這件特定的事情,這將會和其他任何方法一樣快......因爲它只是一次更新表格就不會那麼糟糕。這意味着它運行一次來​​更改數據庫,所以如果它需要比希望的時間長一點,那應該沒問題。我會着眼於試圖優化查詢..如果你可以發佈一個查詢的解釋,所以我們可以看到你如何索引,這將有助於非常感謝 –

+0

感謝您的答覆,生病明天看看並接受:D是的,我也不相信有空間因爲對於每一個更新的行都必須進行新的選擇。索引存在於id上,並且不存在於名稱上。所以選擇速度很快,並且更新不會重建任何索引。 – Sharky

0
UPDATE table_x AS upd 
    SET upd.Name = CONCAT(upd.Name, '-', upd.Id) 
    WHERE upd.id IN(
        SELECT sel.id 
         FROM table_x AS sel 
         WHERE sel.Name = upd.Name 
          AND sel.Id != upd.Id 
       ); 
+2

對不起,我認爲我忘了提及爲安全起見,新的唯一名稱可能不包含該id。該名稱必須附加一個從1開始的連續編號,用於每組重複項。 – gunner1095

0

首先,你應該保存的副本ID在臨時桌子。


Drop temporary table if not exist temp; 

Create temporary table temp (
Select max(id)'id' from table_x group by Name having count(*)>1 
); 

Delete from table_x as x,temp as t where x.id = t.id; 

只是這樣做反覆... ...之後,設置獨特的鍵名稱字段U將得到唯一的行..