web-dev-qa-db-ja.com

CTEまたはネストされたクエリの各行でSELECTを実行しますか?

これはPostgreSQLの問題です

ユーザーのツリーを格納するテーブルがあります。

 + ------ + --------- + 
 | id |親| 
 | ------ + ------ | 1 | 0 | 
 | ------ | --------- | 
 | 2 | 1 | 
 | ------ | --------- | 
 | 3 | 1 | 
 | ------ | --------- | 
 | 4 | 2 | 
 | ------ | --------- | 
 | 5 | 2 | 
 | ------ | --------- | 
 | 6 | 4 | 
 | ------ | --------- | 
 | 7 | 6 | 
 | ------ | --------- | 
 | 8 | 6 | 
 + ------ + --------- + 

Tablefunc拡張機能のconnectby関数を使用して、任意のノードから完全なツリーをクエリできます。たとえば、ツリー内のノードの総数に関して、ツリーのサイズを個別にクエリできます。

#1の木のサイズは7です
#5のツリーのサイズは0です
#6のツリーのサイズは2などです。

ここで、このテーブルから可能なすべてのツリーを選択する(これもconnectbyによって実行されます)ようなことを行い、そのサイズをカウントして、---([〜#〜]のレコードを持つ別のデータセットを作成します。 id [〜#〜]および基になるツリーのサイズ(次のように):

 + ------------------ + ------------- + 
 | tree_root_node | tree_size | 
 | ------------------ + ------------- | 
 | 1 | 7 | 
 | ------------------ + ------------- | 
 | 2 | 3 | 
 | ------------------ + ------------- | 
 | 3 | 0 | 
 | ------------------ + ------------- | 
 | 4 | 3 | 
 | ------------------ + ------------- | 
 | 5 | 0 | 
 | ------------------ + ------------- | 
 | 6 | 2 | 
 | ------------------ + ------------- | 
 | 7 | 0 | 
 | ------------------ + ------------- | 
 | 8 | 0 | 
 + ------------------ + ------------- + 

問題は、ツリーをフェッチしてサイズを計算するために、元のテーブルで使用可能なすべての行に対して同じSELECTステートメントを実行できないことです。できたとしても、フェッチされたデータセットを使用して別のデータセットを作成する方法がわかりません。計算されたデータ。

これがPostgresで利用可能ないくつかの関数の単純な使用であるか、そのための関数を作成する必要があるか、または単にこの種のクエリが正確に何と呼ばれるかわからないが、何時間もグーグルしてさらに1時間を検索するかどうかはわかりませんここdba.stackexchangeでは何も返されませんでした。

誰かが正しい方向を指し示すことができますか?

1
Gufran

これが役立つかどうか教えてください。これはMSSQL(T-SQL)構文を使用しているため、postgres用に調整する必要があるかもしれませんが、#treeという名前の一時テーブルを使用して、2つの列idとparentを含み、例のように入力します。

SELECT 1, 0
UNION 
SELECT 2, 1
UNION 
SELECT 3, 1
UNION
SELECT 4, 2
UNION 
SELECT 5, 2
UNION 
SELECT 6, 4
UNION
SELECT 7, 6
UNION 
SELECT 8, 6:

with cte as
(
    select id as currentnode, id as root
    from #tree
    union all
    select t.id as currentnode, cte.root 
    from #tree t join cte on t.parent = cte.currentnode
)
select *
from cte
order by root

上記の再帰的CTEは、あるルートから到達可能なすべてのノードを生成します。できるよ:

SELECT root, count(*)
from cte
group by root

Count(*)クエリは、

root   |  count
----------------
  1    |    8
  2    |    6
  3    |    1
  4    |    4
  5    |    1
  6    |    3
  7    |    1
  8    |    1

次に、それらのそれぞれから1を引くと、示唆した結果を得ることができます。これはあなたが探していたものですか?そうでない場合でも、再帰的CTEはおそらくあなたが必要としていることを助けることができると思います。

1
Aushin

GROUP BYtree_root_nodeをクエリに追加します???

私は間違っているかもしれません。私は製品固有のSQLの専門家ではありませんが、SQL全般において、これが問題を解決するための「正しい方向」であると期待しています。

0
Erwin Smout