2014-02-20 101 views
0

我的數據庫目前有300行,並且在未來幾年內可能會增加到5000行左右。我想知道如何隨機選擇20行。MySQL從300行快速選擇20行隨機行

我發現這裏MySQL select 10 random rows from 600K rows fast(在那裏再次refered到http://jan.kneschke.de/projects/mysql/order-by-rand/)下面的代碼生成一個隨機選擇非常快:

SELECT name 
    FROM random AS r1 JOIN 
     (SELECT (RAND() * 
        (SELECT MAX(id) 
         FROM random)) AS id) 
     AS r2 
WHERE r1.id >= r2.id 
ORDER BY r1.id ASC 
LIMIT 1 

所以在PHP中我嘗試了以下得到20行:

$anfrage = "SELECT name 
    FROM random AS r1 JOIN 
     (SELECT (RAND() * 
        (SELECT MAX(id) 
         FROM random)) AS id) 
     AS r2 
WHERE r1.id >= r2.id 
ORDER BY r1.id ASC 
LIMIT 20"; 

$ergebnis=$db->query($anfrage) 
     or die($db->error); 
while($zeile=mysqli_fetch_assoc($ergebnis))print_r($zeile); 

但是當我運行腳本時,大多數時候我不會得到20行。實際上,從300箇中選出20個不同行的概率約爲48.8%。

我可以更改上面的代碼來獲得真正的行嗎?

+0

的範圍內,你的問題是,r2.id可能是299,所以你將有隻有兩排WHERE 「r1.id> = r2.id」爲真 – nidomiro

+0

@niccomatik我想我必須將Limit設置爲'1'並在循環中執行整個查詢。然後,在每次查詢後,我必須檢查獲得的行是否是新行 - 是如何工作的? – Adam

+2

即使在50000行時,一個簡單的隨機選擇也會很快。 5000行不算什麼。 MySQL可能甚至不會使用索引查詢表的大小更容易掃描表,所以我不知道爲什麼你擔心速度。 – Namphibian

回答

0

如果你讀,你在你的問題提article,你會發現,有3個解決方案:

  • 執行查詢幾次
  • 寫正在執行查詢和存儲存儲過程結果在一個臨時表
  • 實現聯合

所有這些文章中進行了說明。

0

獲得20種隨機名的「慢」的方式是這樣的:

SELECT name 
FROM random 
ORDER BY rand() 
LIMIT 20; 

在300行,這可能也有類似的性能,您所使用的方法。你試過了嗎?我不確定大約5000行,但值得一試。

你的方法基本上是這樣(查詢是一個位簡化):

SELECT name 
FROM random r1 CROSS JOIN 
    (SELECT RAND() * MAX(id) as id FROM random) r2 
WHERE r1.id >= r2.id 
ORDER BY r1.id ASC 
LIMIT 20; 

您假設r2針對與一個不同的值每次迭代進行評價。這種假設可能並非如此。

另一種方法是做到這一點:

SELECT name 
FROM random r1 CROSS JOIN 
    (SELECT count(*) as cnt FROM random) const 
WHERE rand() <= 20.0/cnt; 

不幸的是,這給行的大致數量。每次約20次。也許你真的想要20。在這種情況下,這樣做增加一倍行的預期數量,然後使用order by/limit

SELECT name 
FROM random r1 CROSS JOIN 
    (SELECT count(*) as cnt FROM random) const 
WHERE rand() <= 2*20.0/cnt 
ORDER BY rand() 
LIMIT 20; 
0

你可以創建你偶爾更新改組表:

INSERT INTO random_ids 
SELECT id 
FROM table_name 
ORDER BY RAND(); 

記錄的隨機數插入到您的應用程序中的值;然後使用以下命令:

SELECT * FROM table_name 
INNER JOIN (SELECT id 
    FROM random_ids 
    LIMIT ?,20 
) r1 ON r1.id = table_name.id; 

,由此限制由您的應用程序確定具有[0, <count>)