有時候需求需要隨機從數據庫查詢若干條記錄集,網上搜了一下,幾篇博文都是些重復的.....不知道他們誰抄的誰的,這裡除了介紹提供一種筆者自己想到的方法,本質都是利用mysql 的rand()
第一種方法:
SELECT * FROM reportcard_patient_temp ORDER BY RAND() LIMIT 10
利用mysql的隨機函數order by,這是最容易想到的,筆者在mysql 5.6.27上面explain查看了執行計劃 :
+----+-------------+-------------------------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------------------+------+---------------+------+---------+------+------+---------------------------------+
| 1 | SIMPLE | reportcard_patient_temp | ALL | NULL | NULL | NULL | NULL | 2479 | Using temporary; Using filesort |
+----+-------------+-------------------------+------+---------------+------+---------+------+------+---------------------------------+
1 row in set
可以看出select type 是simple(這裡是單表),在近40萬的數據隨機取了10條時間也只有1.2秒左右,還是可以接受的,並沒有像網上說的哪有要重復查詢多次。
第二種
SELECT * FROM `table` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` ) ORDER BY id LIMIT 10;
這種方法最大的弊端在於如果主鍵不是自增的該如何?當然在主鍵自增的時候還是可以使用的
第三種,這是筆者自己想出的方法,既然要利用mysql自帶的隨機函數,那麼對於不是自增的主鍵,如何把轉化rand()就成了問題的關鍵,利用count(*)這個整數集
SELECT * FROM (
SELECT zyid ,ROUND(COUNT(*)*RAND()*100) AS newno FROM yw_syjgb GROUP BY zyid
)AS t ORDER BY t.newno asc LIMIT 10
同樣的40萬的記錄集,隨機取10條記錄,時間只需要0.2秒左右,可以說比order by rand()提升還是蠻大的,當然也是可以 把 ROUND(COUNT(*)*RAND()*100) AS newno 作為limit後面的值隨機定位記錄集,需要注意的是記錄數當然是得大於100,如果小於100,哈哈除以10或者100不就行了嘛。
基於數據庫層隨機查詢的還有些很多零碎的方法,這裡筆者覺得符合自身業務復的方法其實還很多,比如你可以在程序裡做隨機挑選算法,或者自己實現一個rand()函數。