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

看我在这里有同样的问题,解决方案有:

CREATE TABLE origintable SELECT * FROM origintable2;
ALTER TABLE origintable2 DROP idfield;
CREATE TABLE origintable3 LIKE origintable2;
INSERT INTO origintable3 SELECT * FROM origintable2 ORDER BY RAND();
DROP TABLE origintable2;
ALTER TABLE origintable3 ADD COLUMN idfield INT NOT NULL AUTO_INCREMENT FIRST
, ADD PRIMARY KEY (idfield);
RENAME TABLE origintable TO origintable_bkp;
RENAME TABLE origintable3 TO origintable;
DROP TABLE origintable3;

奇迹般有效!新表,混杂数据,相同结构!

希望能帮助某人

于 2013-12-30T16:56:05.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,
然后 try 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 回答
0

如果您使用 InnoDB 表,它们总是按主键顺序存储。因此,如果您SELECT从表中未指定任何其他ORDER BY,那么您将按该顺序排列行。


错误代码:1075 表定义不正确;只能有一个自动列,它必须定义为一个键 ==> 似乎谎言我不能删除主键,为什么?– 达米安

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

一种解决方法是在表中创建一个额外的列并为其分配随机值,然后您可以按该列排序。

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 回答