隨機查詢,方法可以有很多種。比如,查詢出所有記錄,然後隨機從列表中取n條記錄。使用程式便可實現。可是程式實現必須查詢出所有符合條件的記錄(至少是所有符合條件的記錄id),然後再隨機取出n個id,查詢資料庫。但是效率畢竟沒有資料庫中直接查詢得快。下麵介紹mysql中怎樣隨機查詢n條記錄。 1.最簡單的 ...
隨機查詢,方法可以有很多種。比如,查詢出所有記錄,然後隨機從列表中取n條記錄。使用程式便可實現。可是程式實現必須查詢出所有符合條件的記錄(至少是所有符合條件的記錄id),然後再隨機取出n個id,查詢資料庫。但是效率畢竟沒有資料庫中直接查詢得快。下麵介紹mysql中怎樣隨機查詢n條記錄。
1.最簡單的辦法order by rand(),示例
select * from question q where q.`level`=1 order by rand() limit 1;
此寫法,可以將查詢出的結果集打亂,limit n條記錄後,得到n條隨機的記錄,這n條記錄也是隨機順序的,就是效率有點慢,但是很隨機。
2.如果記錄id保持連續增長,中間不間斷,則可以用其它方式替代上述語句,示例
#隨機查詢(記錄大於某個數,效率高) select q1.* from question q1 inner join (select (min(q2.id) + round(rand()*(max(q2.id) - min(q2.id)))) as id from question q2 where q2.`level`=1) as t on q1.id >= t.id limit 1; #效率略低 select q.* from question q where q.id > (select t.id from ( select (min(q2.id) + round(rand()*(max(q2.id) - min(q2.id)))) as id from question q2 where q2.`level`=1 ) t) limit 1; #效率極低,比order by rand還低(可能針對每條記錄都作了子查詢,結果不不連續,很隨機) select q.* from question q where q.id > (select (min(q2.id) + round(rand()*(max(q2.id) - min(q2.id)))) from question q2 where q2.`level`=1) limit 1;
法2的實現原理是,找出符合條件的記錄的id範圍[minId,maxId],然後隨機生成一個id,使id在範圍內,演算法為id=minId+[0,maxId-minId], [0,maxId-minId]可使用round四捨五入函數和rand隨機函數實現。然後大於等於此id的記錄既是符合條件的隨機的記錄。上述寫法僅針對查詢出一條記錄。如果查詢出n條記錄則sql語句改為:
select q1.* from question q1 inner join (select (min(q2.id) + round(rand()*(max(q2.id)-2 - min(q2.id)))) as id from question q2 where q2.`level`=1) as t on q1.id >= t.id limit 3;
如上,隨機取連續的3條記錄,max的值減掉二,就是使範圍縮小2,保證隨機出來的id,大於等於它時仍可查出3條記錄。
如果 maxId-(n-1)-minId為負數,就是說數據記錄範圍內沒有n條記錄,則上述語句報錯,改進版如下:
select q1.* from question q1 inner join ( select (min(q2.id) + round(rand()* ( case when (max(q2.id)-2)>min(q2.id) then max(q2.id)-2 - min(q2.id) else 0 end ))) as id,min(q2.id) as minId,max(q2.id) as maxId from question q2 where q2.`level`=2 ) as t on q1.id >= t.id and q1.id between t.minId and t.maxId limit 3;
附上隨機函數的測試代碼:
select 10*RAND(); #[0,10) select FLOOR(10*RAND());#[0,9] select CEILING(10*RAND()); #[1,10] select ROUND(10*RAND()); #[0,10]