每个选定的父母组中的每个成员(以及他们自己的父母)选择一组多个孩子

时间:2019-05-19 14:18:26

标签: sql json postgresql recursive-query

我使用PostgreSQL构建了以下方案-

Table A:
    id | name
    1  | a
    2  | b 
Table B:
    id | parent-A-id  | searchValue | dataB
    1  | 1            | val1        | a
    2  | 2            | val2        | b
    3  | 2            | val2        | c
Table C:
    id | parent-A-id  | dataC
    1  | 1            | x
    2  | 2            | y
    3  | 2            | z
Table D:
    id | parent-A-id  | parent-B-id | searchValue-REF 
    1  | 1            | 1           | val1
    2  | 2            | 2           | val2
    2  | 3            | 2           | val2
    2  | 3            | 3           | val2

我正在尝试检索以下数据-

给定N,仅使用符合searchByVal-REF上运行的函数的项D,找到n个数量的B,其父级A和子级C的子集,这意味着计算出计算结果(例如-位置),对N值。

基于N的数据输出示例为-

[
    {
        A.name : "a",
        A.id : 1
        B.id : 1,
        B.dataB : "a",
        [{C.id : 1, C.dataC : "x"}],
        computedVal : someVal
    },
    {
        A.name : "b",
        A.id : 2
        B.id : 2,
        B.dataB : "b",
        [{C.id : 2, C.dataC : "y"}],
        computedVal : someVal
    },
     {
        A.name : "b",
        A.id : 2
        B.id : 3,
        B.dataB : "c",
        [{C.id : 2, C.dataC : "y"}, {C.id : 3, C.dataC : "z"}],
        computedVal : someVal
    }
]

数据基本上是B的行以及每个B的B个父级A和每个B的n个子级C,这些行的序列化数组以每行B的单列表示。

我不确定是否过于复杂,但是目前我正试图通过将结果数组转换为序列化的json,将一组记录C分组到单个列中。但是,由于我试图在外部查询上引用子查询,因此我尚未设法使其正常工作,因为我认为该查询过于嵌套,因此失败了。

这就是我坚持的地方-

SELECT
  b_items_found.*,
  row_to_json(C_json_arr) as C_list
FROM
  (
    SELECT
      *
    FROM
      (
        SELECT
          array_agg("parent-C-id") as selected_Cs,
          "parent-B-id",
          computedVal
        FROM
          (
            SELECT
              ComputeA(searchValue-REF) AS computedVal,
              "parent-B-id",
              "parent-C-id"
            FROM
              D
              CROSS JOIN (
                SELECT
                  ComputeC(N)
              ) AS r
            WHERE
              ComputeB(searchValue-REF)
            ORDER BY
              ComputeA(searchValue-REF)
          ) select-b-items
        GROUP BY
          "parent-B-id",
          computedVal
      ) b_and_c
      JOIN B ON b_and_c."parent-B-id" = B.id
      JOIN A ON B."parent-a-id" = A.id
  ) b_items_found,
  (
    SELECT
      array_agg(row_to_json(t)) as m
    from
      (
        SELECT
          *
        from
          C
        WHERE C.id = ANY(b_items_found.selected_Cs)
      ) t
  ) C_json_arr

当前结果为-

  

表“ b-items-found”有一个条目,但是不能从查询的这一部分中引用。

我想知道是否有一个单一的查询解决方案,或者应该将其分为几个查询(查询和处理服务器端)。

运行PostgreSQL 9.6.8

1 个答案:

答案 0 :(得分:1)

尽管查询看起来确实过于复杂,但是您的主要问题是您正在尝试访问查询中的临时表b_items_found,优化器可能会决定首先执行以下查询,这就是为什么您无法引用它的原因(没有兄弟姐妹参考,只有孩子)。

为此,您必须使用CTE(Common Table Expression),如下所示:

WITH b_items_found AS (
    SELECT
      *
    FROM
      (
        SELECT
          array_agg("parent-C-id") as selected_Cs,
          "parent-B-id",
          computedVal
        FROM
          (
            SELECT
              ComputeA(searchValue-REF) AS computedVal,
              "parent-B-id",
              "parent-C-id"
            FROM
              D
              CROSS JOIN (
                SELECT
                  ComputeC(N)
              ) AS r
            WHERE
              ComputeB(searchValue-REF)
            ORDER BY
              ComputeA(searchValue-REF)
          ) select-b-items
        GROUP BY
          "parent-B-id",
          computedVal
      ) b_and_c
      JOIN B ON b_and_c."parent-B-id" = B.id
      JOIN A ON B."parent-a-id" = A.id
  ),
  C_json_arr AS (
    SELECT
      array_agg(row_to_json(t)) as m
    from
      (
        SELECT
          *
        from
          C
        WHERE C.id = ANY(b_items_found.selected_Cs)
      ) t
  )
SELECT
  b_items_found.*,
  row_to_json(C_json_arr) as C_list
FROM b_items_found, C_json_arr

但是,由于您的查询与您的表结构不匹配,因此未经测试。