1

階層データであるscopeという名前の自己参照テーブル(私のuser_accountスキーマ内)があります-いくつかのサンプルデータ(Postgres 9.4):

*****編集:******

SQL フィドルを作成しました: http://sqlfiddle.com/#!15/43ff9/2/0より詳細な例を示します。JSON 出力の最下層の繰り返しの性質に注意してください。参考までにこちらの情報を残しておきます。

*****編集終了*****

user_account.scope

id  name             parent_id
1   user             NULL
2   user:create      1
3   user:delete      1
4   user:modify      1
5   user:modify:all  4
6   user:modify:some 4
7   user:modify:ex   4

明らかに、最上位のスコープにはparent_idがなく、複数のレベル(任意)に深くなる可能性があります。

テーブル全体をネストされた JSON オブジェクトとして再帰的に返す SQL クエリを作成しようとしています。私はこれでほとんど成功しました:

WITH json_agg_scope_cte AS (
  WITH scope_cte AS (
    WITH RECURSIVE sub_scopes_cte AS (
      SELECT
        s.*,
        NULL :: JSON AS sub_scopes
      FROM
        user_account.scope s
      WHERE NOT EXISTS(
          SELECT 1
          FROM user_account.scope
          WHERE parent_id = s.id
      )
            AND s.deleted = FALSE

      UNION ALL

      SELECT
        s.*,
        row_to_json(ssc) AS sub_scopes
      FROM
        sub_scopes_cte ssc
        JOIN user_account.scope s
          ON s.id = ssc.parent_id
             AND s.deleted = FALSE
    )

    SELECT
      id,
      scope,
      json_agg(sub_scopes) AS sub_scopes
    FROM sub_scopes_cte ssc
    WHERE parent_id IS NULL
    GROUP BY 1, 2
  )

  SELECT
    s.*,
    sc.sub_scopes
  FROM user_account.scope s
    INNER JOIN scope_cte sc
      ON s.id = sc.id
)

SELECT json_agg(json_agg_scope_cte.*) AS scopes
FROM json_agg_scope_cte

ただし、問題は、サブスコープが最上位アイテムの配列としてリストされていることです (json_agg(sub_scopes) 部分のため) が、単純な NULL またはネストされたものに対する単一のオブジェクトとしてのみリストされます (row_to_json( のため) ssc) 部分)。また、サブスコープごとに 1 回ずつ、JSON 内で親を繰り返します。

私が得ているもの:

"scopes":
[{
  "scope": "top_scope"
  "sub_scopes":
  [{
     "scope": "mid_scope"
     "sub_scopes": // NOT an array, needs to be
     {
        "scope": "bottom_scope_1"
        "sub_scopes": NULL // Should be an array with NULL in it, consistent with format of others
     }
  },
  {
    "scope": "mid_scope" // repeated, bad
    "sub_scopes":
    {
      "scope": "bottom_scope_2"
      "sub_scopes": NULL
    }
  }]
}]

私が欲しいもの:

"scopes": 
[{
  "scope": "top_scope"
  "sub_scopes":
  [{
     "scope": "mid_scope"
     "sub_scopes": // array
     [{
        "scope": "bottom_scope_1"
        "sub_scopes": [NULL] // array as well!
     },
     {
        "scope": "bottom_scope_2"
        "sub_scopes": [NULL]
     }]
  }]
}]

row_to_json を json_agg に変更しようとしましたが、再帰呼び出し内で集計関数を使用できません。A) このクエリを修正する方法、または B) json を "修正" して、必要に応じて値をマージする postgres の方法に関する提案はありますか? これで永遠に遊んでいますが、運がありません。

ありがとう!

4

0 に答える 0