2

テーブル内のすべてのレコードをシャッフルできる MySQL のプロシージャを作成したいと考えています。これまでのところ、これは私が今持っているものです。

/*
    SHUFFLE A TABLE PROCEDURE
*/

DELIMITER $$

USE `nologinsdb`$$

DROP PROCEDURE IF EXISTS `shuffle_record_table`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `shuffle_record_table`()
BEGIN
    DROP TABLE IF EXISTS record_table2;

    CREATE TABLE record_table2 LIKE record_table;

    INSERT INTO record_table2 SELECT * FROM record_table ORDER BY RAND();

    DROP TABLE record_table;

    RENAME TABLE record_table2 TO record_table;
END$$

DELIMITER ;


CALL shuffle_record_table();

そして、私は何かを理解していません

SELECT * FROM record_table ORDER BY RAND()

ランダムな順序になりますが、テーブルに挿入すると、record_table2テーブルと同じ順序になりrecord_tableます。

理解できない。

ありがとう。

4

4 に答える 4

1

テーブル内の行をシャッフルする意味はありません。order by を使用してデータを取得しながら、それらをシャッフルできます。

行の物理的な順序はユーザーにとって重要ではありません。ストレージ エンジンは、アクセスを最適化するためにインデックスの順序で配置しています。

于 2013-10-09T18:15:22.540 に答える
0

InnoDB テーブルを使用する場合、それらは常に主キーの順序で格納されます。したがって、SELECTother を指定せずにテーブルから取得するORDER BYと、その順序で行が表示されます。


エラー コード: 1075 テーブル定義が正しくありません。自動列は 1 つしか存在できず、キーとして定義する必要があります ==> 主キーを削除できないのはなぜですか? – ダミアン

InnoDB では、AUTO_INCREMENT カラムがある場合、それがインデックスの最初のカラムである必要があります。通常、主キー インデックスとして定義しますが、主キーを削除する場合は、少なくとも別のインデックスを定義する必要があります。

例: 自動インクリメント主キーを持つテスト テーブルを作成します。

mysql> create table record_table (id int auto_increment primary key);

mysql> insert into record_table values (1), (2), (3);

キーの一部ではない自動インクリメント列を持つことはできません。

mysql> alter table record_table drop primary key;
ERROR 1075 (42000): Incorrect table definition; 
there can be only one auto column and it must be defined as a key

プライマリ キーを削除して、同じ列にセカンダリ キーを追加すると、これは InnoDB を満たします。

mysql> alter table record_table drop primary key, add key (id);
Query OK, 3 rows affected (0.13 sec)

しかし、その列にキーを持たないようにしようとすると、それもエラーになります。

mysql> alter table record_table drop key id;
ERROR 1075 (42000): Incorrect table definition; 
there can be only one auto column and it must be defined as a key

回避策の 1 つは、テーブルに追加の列を作成し、それにランダムな値を割り当てることです。その後、その列を ORDER BY できます。

mysql> alter table record_table add column sort float;

mysql> update record_table set sort = rand();

mysql> select * from record_table ;
+----+----------+
| id | sort     |
+----+----------+
|  1 | 0.439593 |
|  2 | 0.416936 |
|  3 |   0.7659 |
+----+----------+

mysql> select * from record_table order by sort;
+----+----------+
| id | sort     |
+----+----------+
|  2 | 0.416936 |
|  1 | 0.439593 |
|  3 |   0.7659 |
+----+----------+

ランダムな値を更新するだけで、データを前後にコピーすることなくテーブルを「再シャッフル」できます。

mysql> update record_table set sort = rand();

mysql> select * from record_table order by sort;
+----+----------+
| id | sort     |
+----+----------+
|  1 | 0.137319 |
|  3 | 0.329505 |
|  2 | 0.348292 |
+----+----------+
于 2013-10-09T18:04:11.770 に答える
0

ここでhttp://dev.mysql.com/doc/refman/5.1/en/create-table.html
彼らは言う:

LIKE を使用して、元のテーブルで定義された列属性とインデックスを含む、別のテーブルの定義に基づいて空のテーブルを作成します。

つまり、主キーも新しいテーブルにコピーされ、行の順序が保持されます。
新しいテーブルに主キーをドロップするだけです:

CREATE TABLE record_table2 LIKE record_table;
ALTER TABLE record_table2 DROP PRIMARY KEY;
INSERT INTO record_table2 SELECT * FROM record_table ORDER BY RAND();

-----編集-----

主キー列にauto_icrementがあるために上記の解決策が機能しない場合は、
試してみてくださいCREATE TABLE x AS SELECT * FROM y。これはインデックスとキーをコピーしません:

create table x( 
  x int primary key auto_increment,
  y int );

insert into x( y ) values( 1 ), (3 ), (2),(5),(4);

select * from x;
+ ------ + ------ +
| x      | y      |
+ ------ + ------ +
| 1      | 1      |
| 2      | 3      |
| 3      | 2      |
| 4      | 5      |
| 5      | 4      |
+ ------ + ------ +

5 rows

create table y as select * from x order by rand();

select * from y;

+ ------ + ------ +
| x      | y      |
+ ------ + ------ +
| 2      | 3      |
| 4      | 5      |
| 3      | 2      |
| 1      | 1      |
| 5      | 4      |
+ ------ + ------ +

5 rows
于 2013-10-09T18:14:22.580 に答える