Как получить все дочерние элементы узла в древовидной структуре? SQL-запрос?

таблица - пользователей

столбцы - (userId, name, managerId)

строк -

(1,nilesh,0)
(2,nikhil,1)    
(3,nitin ,2)  
(4,Ruchi,2)

Если я дам id пользователя, он должен перечислить всех сообщающих ему людей . если я дам userId = 2, он должен вернуть 3,4.

это правильный запрос

SELECT ad3.userId
FROM user au , user  au2 , user  au3
WHERE 
    ad.managerId = ad2.managerId AND 
    ad3.managerId = ad2.userId AND
    ad.userId=2

есть ли эффективный способ управления древовидной структуры в БД ? Как насчет правого и левого пути листа ?

4 ответов


на мой взгляд, проблема с моделью списка смежности заключается в том, что в SQL становится трудно иметь дело, особенно когда вы не знаете, насколько глубоко вложена ваша древовидная структура.

"левый и правый лист", который вы упомянули, вероятно, является вложенной моделью набора и позволяет хранить такие вещи, как это

LFT   RGT   Name
1     8      nilesh
2     7      nikhil
3     4      nitin
5     6      Ruchi

тогда вы можете найти всех подчиненных anyones просто

SELECT Name FROM Hierarchy WHERE LFT BETWEEN @LFT AND @RGT

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

есть очень хороший учебник здесь


Я использую текстовое поле для работы с деревьями в SQL. Это проще, чем использовать значения left/right.

давайте возьмем пример из статьи MySQL:

+-----------------------+
| name                  |
+-----------------------+
| ELECTRONICS           |
|  TELEVISIONS          |
|   TUBE                |
|   LCD                 |
|   PLASMA              |
|  GAME CONSOLES        |
|  PORTABLE ELECTRONICS |
|   MP3 PLAYERS         |
|    FLASH              |
|   CD PLAYERS          |
|   2 WAY RADIOS        |
|    FRS                |
+-----------------------+

это приведет к такой таблице:

Id      ParentId        Lineage     Name

1       null            /1/         ELECTRONICS
2       1               /1/2/       TELEVISIONS
3       2               /1/2/3/     TUBE
4       2               /1/2/4/     LCD
5       2               /1/2/5/     PLASMA
6       6               /1/6/       GAME CONSOLES
7       1               /1/7/       PORTABLE ELECTRONICS
8       7               /1/7/8/     MP3 PLAYERS
9       8               /1/7/8/9/   FLASH
10      7               /1/7/10/    CD PLAYERS
11      1               /1/11/      2 WAY RADIOS
12      11              /1/11/12/   FRS

найдите все переносные файлы, которые вы просто используете в Lineage from portables:

SELECT * FROM theTable WHERE Lineage LIKE '/1/7/%'

плюсы:

  • вам нужно сделать обновление после каждой вставки, чтобы добавить ПК к Линии

предложение:

Я обычно добавляю еще один столбец, где я помещаю путь в виде текста (например 'electronics/televisions/tube')


что-то вроде этого (ANSI SQL):

WITH RECURSIVE emptree (userid, name, managerid) AS (
    SELECT userid, 
           name, 
           managerid
    FROM the_table 
    WHERE userid = 2

    UNION ALL

    SELECT c.userid, 
           c.name,
           c.managerid
    FROM the_table c
       JOIN emptree p ON p.userid = c.managerid
)
SELECT *
FROM emptree

SELECT user.id FROM user WHERE user.managerid = 2

это то, что вы хотите?