Выберите группу из нескольких детей на каждого члена выбранной группы родителей (также с их собственными родителями) - PullRequest
0 голосов
/ 19 мая 2019

У меня есть следующая схема, построенная с использованием 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, найдите количество B, его родительский A и aподмножество дочерних элементов C, использующих только те элементы D, которые соответствуют функции, выполняемой в searchByVal-REF, что означает вычисленный результат (например, местоположение) по значению 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
    }
]

Данные в основном представляют собой строки Bs и родителя A каждого B & n потомков C каждого B в сериализованном массиве строк, представленных в одном столбце на строку B.

Я не уверен, слишком ли это усложняю, но в данный момент я пытаюсь сгруппировать набор записей C в один столбец, превратив массив результатов в сериализованный json.Но мне еще не удалось заставить его работать, поскольку я пытаюсь сослаться на подзапрос во внешнем запросе, который завершается неудачей, так как я считаю, что запрос слишком вложенный.

Это то место, где я застрял-

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 Ответ

1 голос
/ 20 мая 2019

Хотя запрос действительно выглядит слишком сложным, ваша основная проблема заключается в том, что вы пытаетесь получить доступ к временной таблице b_items_found в запросе, когда оптимизатор может решить сначала выполнить следующий запрос, поэтому вы не можете ссылаться на него (нет братья и сестры, только дети).

Для этого вам нужно использовать CTE ( Общее табличное выражение ), например:

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

Однако это не проверено, поскольку ваш запрос не соответствует структуре таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...