2016-05-24 15 views
0

私はfragmentsというテーブルを持っています。テーブルには単語と文章の束が入っています。私はランダムなフラグメントを選択して、ランダムな "文章"を作りたいと思っています。私は指定された長さに達するまでこれを続けて、結果の文字列を返します。 PostgreSQLでこれを行う最善の方法は何ですか?あなたはこのために再帰CTEを使用することができますPostgreSQLのテーブルから半ランダムな文字列を作成する

world hello hello world 

http://sqlfiddle.com/#!15/0a88ca/1

答えて

1

上記の例のテーブルと私はバックのような何かを得ることを期待する 20の所望の長さを考えると

id | text 
---------------- 
1 | hello 
2 | world 

WITH RECURSIVE recCte (sentence, length) AS 
(
     --recursive seed 
     SELECT 
     CAST("text" AS VARCHAR(200)) as sentence, 
     1 as length 
     FROM (SELECT "text" FROM test.fragments ORDER BY random() LIMIT 1)frag 

     UNION ALL 

     --recursive term 
     SELECT 
      CAST(recCTE.sentence || ' ' || frag.text as VARCHAR(200)), 
      recCTE.length + 1 
     FROM 
      reccte, (SELECT "text" from test.fragments ORDER BY random() LIMIT 1)frag 
     WHERE recCTE.length <= 20 --Sentence word length 
    ) 
    --Select the full sentence made 
    SELECT sentence FROM recCTE WHERE length = 20; 

これは少し関わっていますが、完璧ですあなたのニーズに合わせて再帰CTEクエリは、3つの部分で構成されています。

  1. 再帰的なシード - これは、非再帰的なクエリの部分です。これはクエリの出発点です。私たちはテーブルからランダムな単語を1つだけ取ります。
  2. 再帰的な用語 - これは再帰的なクエリの部分です。それはそれ自身を...FROM recCTE ...と呼んでいます。再び、テーブルからランダムに1つの単語をつかみ、それを文章の上に貼り付けます。これを実行している間、私たちは反復の深さを追跡し、20回のループの後に停止することができます。
  3. 再帰的なCTEから完全な文を選択するための最後のselect文。各繰り返しはレコードを作成するので、20にしたレコードを取得するだけです。文の長さを変更するには、再帰的CTEおよび最終的なSelect文で「20」を変更します。文字の長さを使用したバージョンを追加する

製作中:

我々はフラグメントテーブルからランダムなテキストを取得するためにORDER BY random() LIMIT 1を使用する必要があるためこれは少しトリッキーですが、ORDER BYをすることはできません再帰CTEではLIMITです。だから、正確に20文字を得ることは難しいですが、...私たちはかなり近いある、< = 20を得ることができます:

WITH RECURSIVE recCte (sentence, length) AS 
    (
     SELECT 
     CAST("text" AS VARCHAR(200)) as sentence, 
     length("text") as length 
     FROM (SELECT "text" FROM test.fragments ORDER BY random() LIMIT 1)frag 

     UNION ALL 

     SELECT 
      CAST(cte.sentence || ' ' || frag.text as VARCHAR(200)), 
      cte.length + 1 + length(frag.text) 
     FROM 
      reccte cte, (SELECT text FROM test.fragments ORDER BY random() LIMIT 1) frag 
     WHERE 
     length(frag.text) < (20-cte.length) 
     AND cte.length <= 20 --Sentence word length 

    ) 

SELECT sentence, length FROM recCTE ORDER BY length DESC LIMIT 1; 

大きな変化をここで文字長を計算し、中にこの制限を追加するLengthフィールドを変更します再帰的項の句のWHERE。最後に、ORDER BY length DESCでcteのレコードを文字の長さでソートし、LIMIT 1を使って作成した最大のものを取得します。

+0

恐ろしい!私はそれが再帰的なクエリであると考えましたが、私は実装上失われました。完全な答えをありがとう。 –

関連する問題