0

以下は、私が持っているテーブル形式です。テーブル名 :: USERS

userid reporttouserid
------ ------------
101    NULL
102    101
103    102

ここで、102 と 103 の両方である 101 未満のすべての子ユーザー ID をリストするクエリが必要です (親の 102 が 101 未満であるため、103 は間接的に 101 未満です)。

postgresql で共通テーブル式を見たことがありますが、その方法がわかりません。

4

1 に答える 1

5

PostgreSQLのドキュメントでは、このトピックについて説明しています。そのページの再帰的 CTE の例を参照してください。

再帰的 CTE は把握するのが少し難しい場合がありますが、一度使用すると非常に強力です。ドキュメントを読んで、少し試してみてください。あなたはそれを得るでしょう。

(質問には常に PostgreSQL のバージョンを記載し、必要な出力を表形式で表示してください)。

与えられたデモ データ:

create table users (
  userid integer primary key,
  reporttouserid integer references users(userid)
);

insert into users(userid, reporttouserid) values (101,null), (102,101), (103,102);

(可能な場合は質問でこれを提供してください。作成するのは面倒です)

次のような方法でグラフを再帰的にたどることができます。

WITH RECURSIVE flatusers(userid, reporttouserid, baseuserid) AS (
    SELECT userid, reporttouserid, userid AS baseuserid 
    FROM users WHERE reporttouserid IS NULL
    UNION ALL
    SELECT u.userid, u.reporttouserid, f.baseuserid
    FROM flatusers f
    INNER JOIN users u ON f.userid = u.reporttouserid

)
SELECT * FROM flatusers;

次のような出力を生成します。

 userid | reporttouserid | baseuserid 
--------+----------------+------------
    101 |                |        101
    102 |            101 |        101
    103 |            102 |        101
(3 rows)

そこからどこに行くべきかを理解できると確信しています。使用する前に、その再帰 CTEを理解していることを確認してください。

PostgreSQL (少なくとも 9.4 以前) は (残念ながら) 非再帰的な CTE であっても、quals を CTE 用語にプッシュダウンできないことに注意してください。クエリに追加WHERE baseuserid = 101すると、クエリはフラット化されたテーブル全体を生成し、そのほとんどを破棄します。1 つのbaseuseridに対してのみこの再帰操作を実行する場合は、再帰 CTE 用語の静的結合部分のWHERE後に適切な節用語を追加する必要があります。WHERE reporttouserid IS NULL

于 2013-11-12T00:53:06.440 に答える