2012-04-23 8 views
0

私は3つのランダムなスタンプを取得したいと思います。このクエリはランダムなスタンプを返しますが、同じ国からのものである可能性があります。私がGROUP BY country_idを追加すると、国ごとに3つのスタンプが得られますが、各国の最初のスタンプだけです。ランダムなレコードですが、各カテゴリから最大1つです

SELECT `stamps`.`stamp_id`, `countries`.`country_name_cs` FROM `stamps` 
LEFT JOIN `countries` ON countries.country_id = stamps.country_id 
WHERE (stamps.stamp_enabled = 1) ORDER BY rand() ASC LIMIT 3 

クエリプロファイル(#Ezequiel Muns溶液)

starting    0.000232 
Opening tables  0.000047 
System lock   0.000013 
Table lock   0.000635 
optimizing   0.000036 
statistics   0.000022 
preparing    0.000023 
Creating tmp table 0.000293 
executing    0.000004 
Copying to tmp table 0.060066 
Sorting result  0.013835 
Sending data   0.089164 
removing tmp table 0.000632 
Sending data   0.000026 
init     0.000048 
optimizing   0.000014 
statistics   0.000061 
preparing    0.000028 
Creating tmp table 0.000326 
executing    0.000004 
Copying to tmp table 0.353176 
Sorting result  0.000158 
Sending data   0.000038 
end     0.000005 
removing tmp table 0.000018 
end     0.000006 
query end    0.000004 
freeing items   0.000575 
removing tmp table 0.002363 
closing tables  0.000023 
logging slow query 0.000004 
cleaning up   0.000009 

id  select_type  table  type  possible_keys  key   key_len  ref   rows  Extra 
1  PRIMARY  <derived2>  ALL  NULL    NULL  NULL  NULL   12679  Using temporary; Using filesort 
1  PRIMARY  c    eq_ref  PRIMARY    PRIMARY  4   s.country_id 1  
2  DERIVED  stamps   ALL  NULL    NULL  NULL  NULL   12679  Using where; Using temporary; Using filesort 
+0

ここに時間を入れたい場合は、これを行うための効率的な方法を説明するページがあります:http://jan.kneschke.de/projects/mysql/order-by-rand/ – ilanco

+0

こんにちはIlanco私は私の例には適用できません。どうぞ私を助けてくれますか? – tomasr

+0

これは本当に驚くべきことではありません。私が言ったように、RAND()のORDER BY RAND()はテーブル全体を読み込む必要があります(選択した列がインデックスされていても、他の唯一の解決策は、PHP(または別のアプリケーション言語)を使用して3つのランダムな国IDを選択し、それぞれにランダムなスタンプを1つ追加することです。 –

答えて

1

次のクエリを試すことができ、これは最初の3つのランダムな国を選択し、国によって混合スタンプテーブルと結合した後、グループ行います。効率的ではありませんが、小規模なデータセットには有効です。

SELECT 
    mixed_stamp.stamp_id, 
    random.country_name_cs 
FROM 
    (SELECT * FROM stamps ORDER BY RAND()) AS mixed_stamp 
LEFT JOIN (SELECT country_id FROM countries ORDER BY RAND() LIMIT 3) random ON (random.country_id = mixed_stamp.country_id) 
GROUP BY random.country_id 
2
SELECT 
    c.country_id, 
    c.country_name_cs, 
    s.stamp_id 
FROM country c 
    JOIN (
     SELECT * 
     FROM stamps 
     WHERE stamp_enabled = 1 
     ORDER BY RAND() 
    ) AS s ON c.country_id = s.country_id 
GROUP BY c.country_id, c.country_name_cs 
ORDER BY RAND() 
LIMIT 3; 

あなたはまず、それぞれの国の最初の(ランダムに選ばれた)スタンプにリストアップトリムして、グループそして、それぞれのスタンプではなく、ランダムな順序ですべての国に参加。外側のクエリのORDER BYは、あなたが選択した国をランダム化し、その後LIMITはデビッド・Zのようにちょうど3

を返し、非効率的、と述べました。

+0

さらに効率的ですか?それは100のトゥサンドレコードで動作します。 – tomasr

+0

私は実際にはわかりません。その量のデータで自分自身をテストしなければならないでしょう。それは耐えられることに終わるかもしれません。 ORDER BY RAND()は常にテーブル全体をスキャンするので、非効率です。 効率を上げるために、SQLを使用してDBMSではなくアプリケーションコードでランダム化を行いますが、それはすべて別の質問になります。 –

+0

私は13のtousandsのレコードでテストし、クエリはうまくいっていますが、半分の時間がかかります。それは私のクエリ(クエリプロファイルがアップ)より約10倍遅いです。より多くの記録があれば、それは最悪と最悪になるだろうと私は思います。どのように改善するのですか?問題は、テーブルスタンプ(国ではない)のランダムソートのみです。 – tomasr

関連する問題