來源:http://www.hxstrive.com/article/48.htm
1、隨機排序後獲取第一行
獲取隨機記錄的常見SQL做法,就是對查詢結果進行隨機排序,然後獲取第一行。如:select * from bugs order by rand() limit 1;
這種方法在數據據量非常小的時候,性能不會有什麼大的影響。如果數據量非常龐大時,這將是致命的(因爲你需要遍歷整個表進行排序)。如果採用隨機函數的返回值進行排序,則排序就跟記錄本身沒有任何關係,則每次排序後的數據是不一樣的,這樣數據的排序就不能被複用。使用隨機函數排序,則不能使用數據庫的索引進行排序,索引排序是非常快的。不使用索引排序的後果就是不得不遍歷整張表(這是非常慢的)。隨機排序的另一個問題就是,好不容易對整個數據進行了排序,但是隻用了一條數據,太浪費了。
2、在表格ID最大和最小值之間選擇一個隨機數
通過數據庫或者程序中的隨機函數,生成一個指定表ID最小值到最大值之間的隨機數。然後將顯示這個隨機數指定的記錄。如下:
select b1.* from bugs as b1 join (select ceil(rand()*(select max(bug_id) from bugs)) as rand_id) as b2 on (b1.bug_id = b2.rand_id);
注意:
要求主鍵值必須從1開始到最大值,且是連續的。如果漏掉了某些值,則可能獲取不到數據(缺點)。如Bugs表:
bug_id(Bug編號) name(Bug名稱)
1 BugName01
2 BugName02
4 BugName04
6 BugName06
隨機獲取Bugs表中的一條記錄:
select ceil(rand()*(select max(bug_id) from bugs));
有rand() * 6 ==>,如果rand()=0.9,則0.9*6=5.4,向下取整後等於5,從上面的表中可以看出bug_id=5的記錄不存在。
3、隨機找到的下一個有效值
與上面的方案類似,但解決了表中在最小值和最大值之間存在縫隙的情況,這個查詢會返回它隨機找到的第一個有效的值。如下:
select b1.* from bugs as b1 join (select ceil(rand()*(select max(bug_id) from bugs)) as rand_id) as b2 where b1.bug_id>=b2.bug_id order by b1.bug_id limit 1;
這個方法解決了沒有隨機數對應的主鍵值,即方法2的問題。但是在縫隙後面的第一列的選中機率會隨着縫隙的增大而增大。如下:
bug_id(Bug編號) name(Bug名稱)
1 BugName01
2 BugName02
100 BugName001
在上面這章表中隨機數字位於3到100之間的都將選中bug_id=100的這條記錄,那麼bug_id=100這條記錄的選中概率將非常高。
注意:
當表中數據向ID值之間的縫隙不大並且每個值要被等概率選中的重要性不高時可以考慮這種方案