1

これら 2 つのクエリを結合する (またはこれら 2 つを一緒に実行する) 方法を探しています。

SELECT  s
FROM    generate_series(1, 50) s;

このクエリでは:

SELECT id FROM foo ORDER BY RANDOM() LIMIT 50;

次のように50行を取得する方法:

series, ids_from_foo
1, 53
2, 34
3, 23

私は数日間それに取り組んできましたが、それを理解することはできません. どんな助けでも素晴らしいでしょう。

4

2 に答える 2

2

使用するrow_number()

select row_number() over() as rn, a
from (
    select a
    from foo
    order by random()
    limit 50
) s
order by rn;
于 2014-08-29T15:10:27.673 に答える
1

ランダムに並べ替えられたテーブルから上位 n 行を選択するのは、単純で短時間の強引な方法ですが、ランダムに 50 行を選択するには時間がかかります。すべての行をそのようにソートする必要があります。

小規模から中規模のテーブル、または 1 回限りのアドホックな使用に適しています。大きなテーブルで繰り返し使用するには、はるかに効率的な方法があります。主キーのギャップ/アイランドの比率が低い場合は、これを使用します。

SELECT row_number() OVER() AS rn, *
FROM (
   SELECT *
   FROM  (
       SELECT floor(random() * 999999)::int AS foo_id
       FROM   generate_series(1, 55) g
       GROUP  BY 1                     -- trim duplicates
       ) sub1
   JOIN   foo USING (foo_id)
   LIMIT  50
   ) sub2;

テーブルの大きさに関係なく、これは数ミリ秒 (またはそれ以下) の問題になります。
を使用して、パフォーマンスを代替ソリューションと比較してくださいEXPLAIN ANALYZE

説明

  • 999999テーブルの推定行数で、切り上げられます。次の結果に置き換えます。

    SELECT reltuples FROM pg_class WHERE oid = 'foo'::regclass;
    

    最後のANALYZE. 一般的なクエリで式自体を動的に使用することもできます。これは安価です。詳細:

  • 55は、結果の目的の行数 ( 50) に、テーブルのギャップ率を簡単に補うための低い係数を掛けたものであり、(可能性は低いですが可能性はありますが) 重複する乱数です。

  • 言うまでもなく、foo_id索引付けする必要があります。主キーは問題なく機能します。

  • 主キーが 1 付近で始まらない場合 (正確に 1 である必要はありません。ギャップはカバーされます)、最小 pk 値を計算に追加します。

    min_pkey + floor(random() * 999999)::int
    

この関連する回答の詳細な説明:

于 2014-08-29T17:14:23.477 に答える