SQLのランダム関数の使い方についてまとめています。
SQLでランダムを使ったサンプルコード集
以下は、MySQLでのサンプルコードです。MySQLのサンプルデータベースEmployeesを使用しています。
SQLでランダムな数(乱数)を取得する
乱数はrand()で取得可能です。0.0~1.0の間の乱数を取得可能です。整数の乱数を取得するには、floor(切り捨て)関数を組み合わせます。
例えば、5以上20以下の乱数を取得するには、floor(5+rand()*15)と記述します。
mysql> select rand(); +---------------------+ | rand() | +---------------------+ | 0.06205727631417781 | +---------------------+ 1 row in set (0.00 sec) mysql> select floor(5 + RAND() * 15); +------------------------+ | floor(5 + RAND() * 15) | +------------------------+ | 8 | +------------------------+ 1 row in set (0.00 sec) mysql> select floor(5 + RAND() * 15); +------------------------+ | floor(5 + RAND() * 15) | +------------------------+ | 17 | +------------------------+ 1 row in set (0.00 sec) mysql> select floor(5 + RAND() * 15); +------------------------+ | floor(5 + RAND() * 15) | +------------------------+ | 12 | +------------------------+ 1 row in set (0.00 sec)
SQLでランダムな値を テーブルに挿入する
テーブルの値に乱数を挿入することも可能です。以下のサンプルは、同じinsert文ですが、実行するたびに異なる値がテーブルに挿入されます。
mysql> create table employees.randomtable ( r int not null ); Query OK, 0 rows affected (0.12 sec) mysql> insert into randomtable ( r ) values ( floor(5 + RAND() * 15) ); Query OK, 1 row affected (0.01 sec) mysql> insert into randomtable ( r ) values ( floor(5 + RAND() * 15) ); Query OK, 1 row affected (0.01 sec) mysql> insert into randomtable ( r ) values ( floor(5 + RAND() * 15) ); Query OK, 1 row affected (0.01 sec) mysql> select * from randomtable; +----+ | r | +----+ | 7 | | 16 | | 9 | +----+ 3 rows in set (0.00 sec)
SQLでランダムな順番で レコードを取り出す
下記のサンプルは、対象テーブルからランダムな順番で10件のデータを取り出すサンプルです。
ただし、テーブル全体に対して乱数でソートをかけるため、クエリが非常に重くなるので注意が必要。以下のケースでは、10件の取得に3.07秒かかっています。
explainで実行計画をチェックすると、テーブル全体(約28万件)に対してインデックスなしのテーブルフルスキャンを実行していることがわかります。
【関連記事】
▶SQLのexplainは、実行計画を表示 遅いSQLのボトルネックを発見する
件数の少ないテーブルに対しては、有効な方法と言えるでしょう。
select * from salaries order by Rand() limit 10; +--------+--------+------------+------------+ | emp_no | salary | from_date | to_date | +--------+--------+------------+------------+ | 453998 | 49498 | 1988-05-23 | 1988-06-29 | | 269607 | 65039 | 2002-06-08 | 9999-01-01 | | 85666 | 80434 | 1994-01-14 | 1995-01-14 | | 464086 | 62364 | 1999-11-26 | 2000-11-25 | | 441784 | 59685 | 1997-06-26 | 1998-06-26 | | 470206 | 80771 | 1999-05-31 | 2000-05-30 | | 234186 | 65600 | 2001-03-29 | 2002-03-29 | | 451094 | 54430 | 1995-02-10 | 1996-02-10 | | 454337 | 50130 | 1994-10-31 | 1995-10-31 | | 89644 | 57349 | 1992-07-28 | 1993-07-28 | +--------+--------+------------+------------+ 10 rows in set (3.07 sec) mysql> explain select * from salaries order by Rand() limit 10; +----+-------------+----------+------------+------+---------------+------+---------+------+---------+----------+---------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------+------------+------+---------------+------+---------+------+---------+----------+---------------------------------+ | 1 | SIMPLE | salaries | NULL | ALL | NULL | NULL | NULL | NULL | 2838426 | 100.00 | Using temporary; Using filesort | +----+-------------+----------+------------+------+---------------+------+---------+------+---------+----------+---------------------------------+ 1 row in set, 1 warning (0.02 sec)
【関連記事】
▶SQL limitを使ったページング、ランダム抽出、速度改善をおこなう
まとめ
- 乱数はrand()関数で取得可能
- 整数の乱数を取得するにはfloor関数を組み合わせる
- テーブルからランダム順にレコード取得する際は、テーブル件数に注意