web-dev-qa-db-ja.com

ユーザーの名前をランダムな名前に置き換える方法は?

Mysql DBでのみSQLを使用して、関連する2つのテーブルからランダムな名前を使用してsersテーブルの実際のユーザーの姓名を置き換える方法:random_first_namesおよびrandom_last_names。 usersテーブルには25万件を超えるレコードが含まれており、各rundomeテーブルにはsersテーブルの各レコードに対してランダムに選択する必要がある5000を超える名前が含まれています。 SQLのみで実現できますか?

[更新]

Rickの入力に基づいて問題を解決し、以下の完全なSQLスクリプトを共有しました。

2
user1525248

アップデートが遅すぎると判断した場合は、以下の処理を約1000倍高速にすることをお勧めします。

ループ(ストアドプロシージャで実行可能)...

  1. [Re]ランダムに設定されたセットfirst_namesを使用して、 `PRIMARY KEY 1..5000でテーブルを作成します。同上last_names(2番目のテーブル)。
  2. マルチテーブルUPDATE 2つのランダムテーブルに結合された「次の」5000行。使用する ON Users.id % 5000 = RandomFirstNames.id(etc)

ループ終了

テーブルをシャッフルする(ループのステップ1)のようなものです

CREATE TABLE RandomFirstNames (
    id SMALLINT UNSIGNED AUTO_INCREMENT,
    first_name VARCHAR(...),
    PRIMARY KEY(id) )
SELECT first_name FROM FirstNames ORDER BY Rand();

OPの更新後

しないで

SELECT count(id) INTO count_names FROM _RandomFirstNames;

代わりに、これを1回実行します。

SELECT @mask_ct := COUNT(*) FROM _masked_names;

@mask_ct の代わりに count_names;

スキップされたIDについては、CREATE TABLE _RandomFirstNames、IDなし、ALTER TABLE _RandomFirstNames ADD id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY;を使用してIDを取得します。これにより、ギャップのないIDが得られます(何らかの種類のマルチマスタークラスターを使用している場合を除く)。

2
Rick James

ORDER BY Rand()LIMIT 1と組み合わせて使用​​して、ランダムな名前のテーブルのランダムな行を選択できます。

UPDATE users
       SET first_name = (SELECT name
                                FROM random_first_names
                                ORDER BY Rand()
                                LIMIT 1),
           last_name = (SELECT name
                               FROM random_last_names
                               ORDER BY Rand()
                               LIMIT 1);
1
sticky bit

入力のためにリックとスティッキービットをありがとう。 Sticky Bitのソリューションは、実行に長い時間がかかります。リックの答えは最も近いものでした、そして彼のコメントは私が以下で共有している完全な解決策を作成するのに役立ちました。

まず、ランダムな名前を格納する一時テーブルを作成します

DROP TABLE IF EXISTS _RandomFirstNames;
CREATE TABLE _RandomFirstNames (first_name VARCHAR(255));

DROP TABLE IF EXISTS _RandomLastNames;
CREATE TABLE _RandomLastNames (last_name VARCHAR(255));

次に、これらのテーブルをランダムな名前で埋めるプロシージャを作成して、可能な各ユーザーIDごとに1つの名と1つの姓があることを確認します。

DELIMITER $$
DROP PROCEDURE IF EXISTS prepare_randon_names$$
CREATE PROCEDURE prepare_randon_names()
BEGIN
        SELECT @users := id FROM users ORDER BY id DESC LIMIT 0, 1;

        SELECT @mask_ct := COUNT(*) FROM _masked_names._firstnames;
        SELECT @loops := @users/@mask_ct;
        SELECT @count := 0;
        WHILE @count  < @loops DO
                INSERT INTO _RandomFirstNames (first_name)
                SELECT firstname FROM _masked_names._firstnames ORDER BY Rand();

                SELECT @count := @count+1;
        END WHILE;

        SELECT @mask_ct := COUNT(*) FROM _masked_names._lastnames;
        SELECT @loops := @users/@mask_ct;
        SELECT @count := 0;
        WHILE @count  < @loops DO
                INSERT INTO _RandomLastNames (last_name)
                SELECT lastname FROM _masked_names._lastnames ORDER BY Rand();

                SELECT @count := @count+1;
        END WHILE;
END$$
DELIMITER;

これを実行して、追加されたテーブルに増分IDを追加できます。

CALL prepare_randon_names();

ALTER TABLE _RandomFirstNames ADD id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY;
ALTER TABLE _RandomLastNames ADD id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY;

これで、上記で作成したランダムな名前で2つの新しいテーブルを結合することにより、ランダムな名前でユーザーテーブルを更新できます。

UPDATE users u
left join _RandomFirstNames f on f.id = u.id
left join _RandomLastNames l on l.id = u.id
       SET u.first_name = f.first_name,
           u.last_name = l.last_name;

そして最後のステップで、ランダムな名前のテーブルを削除します。不要になったためです。

DROP TABLE IF EXISTS _RandomFirstNames;
DROP TABLE IF EXISTS _RandomLastNames;

メモの要約

  • テーブルにランダムな名前が入力された後に主キーを追加すると、インデックスのスキップ数の問題が解決しました。たとえば、_RandomFirstNamesでは、IDはID 5163まで順次増加し、次に8192(3,029まで)までスキップされ、次に13354まで順次増加し、その後3,029までを16383までスキップしました。_RandomFirstNamesは、 5163名。

  • 250,000レコードのusersテーブルに対して実行すると、whileループ内のcount(...)を回避すると速度が1秒増加しました

1
user1525248