Получить всех родителей / детей записи в таблице - PullRequest
1 голос
/ 22 февраля 2020

У меня есть таблица SQL (Postgres) с именем «Items» со следующей схемой.

id | parent_id | name

Где столбец parent_id является ForeignKey для той же таблицы. (Например, у элементов есть родительские элементы, а у этих элементов могут быть родительские элементы)

Это упрощает иерархию ветвления.

В настоящее время я запрашиваю указанную запись c и использую for loop, чтобы получить каждого из родителей / детей. Это приводит к выполнению многочисленных запросов.

Я хочу сделать запрос к этой таблице, используя идентификатор одного из элементов, и вернуть всех его родителей / детей, используя один запрос.

Я могу сделать это sh, используя .select_related(“parent__parent”) или .prefetch_related(“item_set”) для детей, но оба этих подхода потребуют знания глубины иерархии перед этим.

Есть ли способ Django получить все связанные строки в одном запросе? Raw SQL тоже хорошо.

Ответы [ 2 ]

1 голос
/ 22 февраля 2020

Это рекурсивное решение для получения родительской и дочерней иерархии записи.

select * from 
(WITH RECURSIVE cte_items (id, name, parent_id) AS (
    SELECT id, name, parent_id        
    FROM items
    WHERE id = 1
    UNION ALL
    SELECT e.id, e.name, e.parent_id
    FROM items e
      INNER JOIN cte_items o ON o.id = e.parent_id)
SELECT id, name, parent_id FROM cte_items) child
union
select * from 
(WITH RECURSIVE cte_items (id, name, parent_id) AS (
    SELECT id, name, parent_id        
    FROM items
    WHERE id = 1
    UNION ALL
    SELECT e.id, e.name, e.parent_id
    FROM items e
      INNER JOIN cte_items o ON o.parent_id = e.id)
SELECT id, name, parent_id FROM cte_items) parent
order by parent_id

0 голосов
/ 23 февраля 2020

OP Примечание

Я изменил большой код, предоставленный Николой, следующим образом:

Код немного понятнее и выполняет незначительно меньше действий с таблицей .

where id = 1 в каждом из SELECTS - это фактический идентификатор записи, к которой вы хотите запросить.

WITH parents  AS (
    SELECT id, name, parent_id        
    FROM family
    WHERE id = 1 
    UNION ALL
    SELECT e.id, e.name, e.parent_id
    FROM family e
    INNER JOIN parents o ON e.id = o.parent_id)
, children  as (
    SELECT id, name, parent_id        
    FROM family
    WHERE id = 1  
    UNION ALL
    SELECT e.id, e.name, e.parent_id
    FROM family e
    INNER JOIN children o ON o.id = e.parent_id 
)
SELECT id, name, parent_id FROM parents
UNION
SELECT id, name, parent_id FROM children;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...