Построение иерархического дерева с помощью одного SQL-запроса - PullRequest
2 голосов
/ 31 августа 2011

У меня есть таблица SQL со следующей структурой.

id   - int
par  - int (relational to id)
name - varchar

Столбец par содержит ссылки на id или NULL если нет ссылки, эта таблица предназначена для построения иерархического дерева.

Затем, учитывая данные:

id par  name

1  NULL John
2  NULL Mario
3  1    George
4  3    Alfred
5  4    Nicole
6  2    Margaret

Я хочу получить иерархическое дерево, вплоть допоследний родитель, от данного одиночного id .

Например, я хочу знать дерево от Nicole до последнего родителя.Таким образом, результатом запроса будет:

id par  name

5  4    Nicole
4  3    Alfred
3  1    George
1  NULL John

Обычно я делаю это с повторением запроса SQL снова и снова и построением дерева сервера, но сейчас я этого не хочу.

IsЕсть ли способ добиться этого с помощью одного запроса SQL?Мне это нужно либо для MySQL, либо для PgSQL.

И я также хочу знать, если это возможно, широко ли он поддерживается?В каких версиях MySQL или PgSQL можно ожидать поддержки?

Ответы [ 4 ]

6 голосов
/ 31 августа 2011

Это возможно с помощью одного запроса в Postgres с использованием рекурсивного общего табличного выражения. Это невозможно в MySQL, поскольку это одна из немногих баз данных, которая не поддерживает рекурсивные CTE.

Это будет выглядеть примерно так (не проверено)

WITH RECURSIVE tree (id, par, name) AS (
    SELECT id, par, name 
    FROM the_table
    WHERE name = 'Nicole'

    UNION ALL

    SELECT id, par, name 
    FROM the_table tt
      JOIN tree tr ON tr.id = tt.par
)
SELECT *
FROM tree
1 голос
/ 31 августа 2011

Для Postgres см. http://www.postgresql.org/docs/8.4/static/queries-with.html

MySQL не поддерживает этот синтаксис (если только он не находится в бета-версии / дереве разработки). Oracle имеет нечто подобное, используя connect by prior.

0 голосов
/ 31 августа 2011

Возможно, вам стоит взглянуть на эту статью:

http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

0 голосов
/ 31 августа 2011

В Oracle это делается с помощью:

SELECT [[LEVEL,]] id, par, name FROM my_table
 START WITH name = 'Nicole'
CONNECT BY [[NOCYCLE]] id = PRIOR par
[[ORDER SIBLINGS BY name ASC]]

(мой синтаксис [[…]] обозначает необязательные биты запроса.

MySQL планирует интегрировать такую ​​функцию. Для PostgreSQL естьвам поможет еще один ответ.

...