2016-04-03 24 views
3

誰かがこのSQLクエリがどのように正確に動作するか説明できますか?この再帰SQL CTEは、どのようにして正確に動作しますか?

WITH recursive n(n) AS (
    SELECT 2 n 
    UNION ALL 
    SELECT n+1 FROM n WHERE n<1000 
) 
SELECT a.n 
FROM n a 
    LEFT JOIN n b 
    ON b.n < sqrt(a.n) 
GROUP BY a.n 
HAVING a.n=2 OR MIN(a.n % b.n) > 0; 

これは、PostgreSQLに次のように生成されます。

n 
==== 
251 
887 
601 
647 
577 
... 
9 
(177 rows) 

ライン・バイ・ライン破壊の私の理解:

SELECT 2 n - Nとして数2 [アンカー部材を選択しますのCTE]

UNION ALL - n <から再帰的なコンポーネントn + 1と結合するので、2から1000年

SELECT a.n FROM n a - [CTEの再帰メンバ]

LEFT JOIN n b上記クエリを実行する - 第二セット -

ON b.n < sqrt(a.n)

数の第二のセットと数2〜1000に参加左数の最初の列の平方根よりも小さいですか?

GROUP BY a.n - モジュロBのA = 2又は最小値が0よりも大きい... - 数字のみ

HAVING a.n=2 OR MIN(a.n. % b.n) > 0の最初の列を表示しますか?

これは愚かなクエリですが、それを解読する際の助けに感謝します。適切に固定

+0

ここでは、1000未満の素数を生成することを意図していると思いますが、結果は25,49などが得られるようには見えません。 –

+0

結果をよく見ると、それらの四角形は1000未満ですが、結果に3を含めるために、 'having'節に条件を1つ追加する必要があります。' HAVING = 2 OR = 3 OR MIN(%bn)> 0'です。 –

答えて

4

あなたのクエリ、1000以下の素数のリストを生成します。

WITH recursive n(n) AS (
    SELECT 2 n 
    UNION ALL 
    SELECT n+1 FROM n WHERE n<1000 
) 
SELECT a.n 
FROM n a 
    LEFT JOIN n b 
    ON b.n <= sqrt(a.n)      -- Fix #1 
GROUP BY a.n 
HAVING a.n=2 OR a.n=3 OR MIN(a.n % b.n) > 0 -- Fix #2 
ORDER BY a.n ASC 

Demo.

説明はかなり簡単です:クエリの再帰部分は、単にあなたを与えるための方法です2〜1000までの数字のリスト。再帰句を、連続する整数値が移入された実際の表で置き換えることができます。

これらの番号は、クエリの非CTE部分に入力され、条件b.n < sqrt(a.n)で自身に結合されます。 a側は候補素数を表します。 b側は候補因子を表します。

<<=に変更する必要があります。そうしないと、素数の四角形の根が出力に含まれます。

GROUP BYは、潜在的な素数を候補素数で1つのグループにグループ化します。 HAVING節は、候補素数を均等に分割する1つ以上の候補除数、すなわちMIN(a.n % b.n)がゼロであるすべてのものを削除する。

2番目の修正を必要とする場所です、3の平方根、素数ので、リスト上の最小の候補除数未満2です。したがって、3は候補除数がまったくなくなり、HAVING節によって投げ捨てられます。それを保存するにはOR a.n=3を追加する必要があります。

+0

驚くばかり!ありがとう – OrdinaryHuman

関連する問題