4

約100万レコードのデータベーステーブルがあります。このテーブルで重複する名前をすべて見つけて、一意にする必要があります。

例えば...

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クエリまたはプロシージャでこれを行う効果的な方法はありますか?

前もって感謝します!

4

4 に答える 4

2

これは少し注意が必要です。ローカルホストでテストしましたが、必要な処理が実行されます。ご不明な点がありましたらお知らせください。SQLフィドル

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


編集: これはパフォーマンスのためにうまくいくかもしれません

1.このクエリを最初に実行する

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

私はこれを私のローカルでテストしました、そしてそれはあなたがこれを実行させることができるはずなのでそれは動作します:)

于 2014-06-27T22:31:51.380 に答える
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
                 );
于 2012-07-07T17:20:20.930 に答える
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は、名前フィールドに一意のキーを設定した後、一意の行を取得します。

于 2014-06-28T04:30:47.690 に答える
0

読みやすいソリューション

CREATE TEMPORARY TABLE duplicate_names
SELECT name FROM records_table
GROUP BY name
HAVING count(name) > 1;

SET @row_number = 1;
SET @name = '';
CREATE TEMPORARY TABLE duplicates
SELECT 
CASE 
WHEN @name = name THEN @row_number:=@row_number + 1
  ELSE   
    @row_number:=1 
END AS identifier,
@name:=name AS name,id 
FROM
    records_table WHERE name IN (SELECT name FROM duplicate_names)
ORDER BY records_table.name;
    
UPDATE records_table INNER JOIN duplicates 
ON records_table.id = duplicates.id
SET records_table.name = 
CONCAT(duplicates.name,'-',duplicates.identifier);
于 2021-09-10T08:10:16.423 に答える