在日常開發中,我們通常需要在指定的一張表或多張表中隨機的選擇一條記錄作為顯示。如:廣告展示(從多個廣告商的廣告中隨機選擇乙個)、新聞推薦等等
常見方法如下:
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名稱)
1bugname01
2bugname02
4bugname04
6bugname06
隨機獲取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名稱)
1bugname01
2bugname02
100bugname001
在上面這章表中隨機數字位於3到100之間的都將選中bug_id=100的這條記錄,那麼bug_id=100這條記錄的選中概率將非常高。
注意:當表中資料向id值之間的縫隙不大並且每個值要被等概率選中的重要性不高時可以考慮這種方案。
4、通過程式語言實現
你可以在程式中先獲取所有的主鍵值,然後在主鍵值中隨機選擇乙個,再用這個隨機選中的主鍵值去檢索資訊。如:string sql = select bug_id from bugs;
// 獲取所有的bugs編號,且存放到list中
list bugidlist = getbugsidlist(sql);
// 從列表中中隨機選擇乙個bug編號
int bugid = bugidlist(random(bugidlist.size()));
// 根據隨機bugid值檢索資訊
string bugsql = "select * from bugs where bug_id=" + bugid ;
存在的問題:
1、獲取所有的bugs表的主鍵值,可能超出記憶體處理極限(有非常多的記錄)。
2、查詢必須進行兩次資料庫操作,一次獲取所有key,另一次獲取隨機取出bugid的資訊。如果查詢太複雜,則將非常耗時。
5、通過下標來實現
前面幾種解決方案中都存在這樣那樣的問題,那麼這種解決方案就避免了上面幾種方案中存在的問題。原理如下:計算總的資料行數,隨機選擇0到總行數之間的乙個值,然後利用這個值作為位移來獲取隨機行(orcale資料庫rownum、mysql資料庫的limit可以實現)。如(oracle):select * from (
select a.*, rownum n_index from bugs a
) t where t.n_index=(
select ceil(rand()*select count(*) from bugs
使用這種方案,使用了非sql標準的語法,如rownum這是orace獨有的、mysql的limit等。當你不能保證主鍵是連續的,並且需要每行資料有相同的選中概率時,可以用這個方案。
mysql如何選擇隨機行 使用MySQL選擇隨機行
偶然的你 order by rand 如您所知,大多數人推薦的解決方案無法擴充套件到大型表。set r select floor rand select count from mytable set sql concat select from mytable limit 1 offset r pr...
mysql列表隨機選資料 從MySQL隨機選取資料
從mysql隨機選取資料 2014 06 23 從mysql隨機選取資料最簡單的辦法就是使用 order by rand 方案一 select from table order by rand limit 0,1 這種方法的問題就是非常慢。原因是因為mysql會建立一張零時表來儲存所有的結果集,然後...
mysql隨機顯示記錄 MySQL隨機讀取表中記錄
order by rand 來實現 select from table order by rand 記憶體臨時表 order by rand 是一般通過記憶體臨時表排序,可以通過執行計畫explain中extra欄位顯示using temporary觀察到。由於是記憶體排序,回表過程不涉及機械磁碟i...