3

データベースに 2 つのテーブルがあります。

(1) フレーズ:

t_phrase
========
I like
They prefer
...
Somebody else wants

(2) 場所:

n_id   t_place
====   =======
1      London
2      Paris
...
N      New York

テーブルPHRASESには少なくとも と同じ数の行がありPLACESます。これらの 2 つのテーブルを結合して、それぞれにplace1 つずつすべてのを選択phraseする必要がありますが、フレーズは複数の場所にランダムに分散する必要があります。テーブル全体placesはそれほど大きくありません: おそらく 3 ~ 4,000 行程度WHEREですが、出力を最大で約 200 箇所に制限する追加の節があります。

理想的には、これを 1 つの SQL ステートメントにしたいと考えていますが、これまでのところ、これについて理解できていません。したがって、2 番目のオプションは、 の行を返すストアド関数です(int, varchar, varchar)。このために、私は次のようなことを考えていました。

  1. すべてのフレーズをランダムな順序で選択して varchar の配列に入れる
  2. 一度に 1 つずつ場所をループし、配列の次のフレーズと一緒に返します

どういうわけか、これは非常に非効率的なように思えますが、より良いものを思いつくことはできません.

より良いアイデアを提案できますか?または、さらに良いのは、1 つのステートメント SQL でしょうか?

前もって感謝します。

編集:結果セットでフレーズを繰り返さないでください。少なくとも場所と同じ数のフレーズが常に存在します。

4

2 に答える 2

2
WITH p AS (
    SELECT place, row_number() OVER () AS rn
    FROM   t_place
    WHERE  <some condition>
    )
    , ph AS (
    SELECT phrase, row_number() OVER (ORDER BY random()) AS rn
    FROM   t_phrase
    )
SELECT ph.phrase, p.place
FROM   p
JOIN   ph USING (rn);

両方のテーブルに真にランダムな順序を課すと、これ以上ランダムになることはありません。遅くなるだけです。次の理由により、フレーズにランダムな順序を課します。

少なくとも場所と同じ数のフレーズが常に存在します。

ランダムではない部分が切り取られないように、より大きなセットで行う必要があります。一方、小さいセット (場所) については、ギャップのない数字のシーケンスが適切であるため、最速の方法を選択します

私の例では CTE を使用していますが、サブクエリでも同様に実行できます。CTEウィンドウ関数の両方に PostgreSQL 8.4 以降が必要です。

于 2012-07-05T23:24:19.480 に答える
0

私は次のことがうまくいくと思います:

select (select phrase from phrases order by random() limit 1),
       place
from places

選択内の選択は行ごとに呼び出す必要があるため、毎回異なる値を返す必要があります。

フレーズと場所をランダムに配置したい場合は、Windows 関数を使用できます。

select ph.phrase, p.place
from (select place, row_number() over (order by place) as seqnum
      from places p
     ) p join
     (select phrase, row_number() over (order by random()) as seqnum
      from phrases
     ) ph 
     on p.seqnum = ph.seqnum

これにより、場所が場所ごとに並べ替えられます (または任意のフィールドで実行できます)。フレーズをランダム化し、結果の行番号を結合します。

于 2012-07-05T15:32:46.040 に答える