T-SQL Как получить все элементы из дерева в T-SQL? - PullRequest
2 голосов
/ 24 ноября 2010

У меня проблема с запросом t-sql.

Допустим, у меня есть дерево категорий (ID категорий)

cat_table

 1
 |
 2-\
 |  3-\
 6  |  5
 |  4  |
...   ...

ads_table

ad_ID
category_ID

конечно, столбец category_ID ссылается на столбец ID в cat_table

проблема в том, как получить (рекурсивно?) Все рекламные объявления из всех категорий, для которых самый верхний родитель является 1-й категорией?

Ответы [ 3 ]

9 голосов
/ 24 ноября 2010

попробуйте использовать рекурсивные выражения общих таблиц, иначе говоря, «CTE» (доступно в SQL Server 2005 и более поздних версиях), например:

--go through a nested table supervisor - user table and display the chain
DECLARE @Contacts table (id varchar(6), first_name varchar(10), reports_to_id varchar(6))
INSERT @Contacts VALUES ('1','Jerome', NULL )  -- tree is as follows:
INSERT @Contacts VALUES ('2','Joe'   ,'1')     --                      1-Jerome
INSERT @Contacts VALUES ('3','Paul'  ,'2')     --                     /        \
INSERT @Contacts VALUES ('4','Jack'  ,'3')     --              2-Joe           9-Bill
INSERT @Contacts VALUES ('5','Daniel','3')     --            /       \              \
INSERT @Contacts VALUES ('6','David' ,'2')     --     3-Paul          6-David       10-Sam
INSERT @Contacts VALUES ('7','Ian'   ,'6')     --    /      \            /    \
INSERT @Contacts VALUES ('8','Helen' ,'6')     -- 4-Jack  5-Daniel   7-Ian    8-Helen
INSERT @Contacts VALUES ('9','Bill ' ,'1')     --
INSERT @Contacts VALUES ('10','Sam'  ,'9')     --

DECLARE @Root_id  char(4)

--get 2 and below
SET @Root_id=2
PRINT '@Root_id='+COALESCE(''''+@Root_id+'''','null')
;WITH StaffTree AS
(
    SELECT 
        c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf
        FROM @Contacts                  c
            LEFT OUTER JOIN @Contacts  cc ON c.reports_to_id=cc.id
        WHERE c.id=@Root_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL)
    UNION ALL
        SELECT 
            s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1
        FROM StaffTree            t
            INNER JOIN @Contacts  s ON t.id=s.reports_to_id
    WHERE s.reports_to_id=@Root_id OR @Root_id IS NULL OR t.LevelOf>1
)
SELECT * FROM StaffTree

выход:

@Root_id='2   '
id     first_name reports_to_id Manager_id Manager_first_name LevelOf
------ ---------- ------------- ---------- ------------------ -----------
2      Joe        1             1          Jerome             1
3      Paul       2             2          Joe                2
6      David      2             2          Joe                2
7      Ian        6             6          David              3
8      Helen      6             6          David              3
4      Jack       3             3          Paul               3
5      Daniel     3             3          Paul               3

(7 row(s) affected)

изменить @Root_id, чтобы получить другой вывод:

@Root_id=null
id     first_name reports_to_id Manager_id Manager_first_name LevelOf
------ ---------- ------------- ---------- ------------------ -----------
1      Jerome     NULL          NULL       NULL               1
2      Joe        1             1          Jerome             2
9      Bill       1             1          Jerome             2
10     Sam        9             9          Bill               3
3      Paul       2             2          Joe                3
6      David      2             2          Joe                3
7      Ian        6             6          David              4
8      Helen      6             6          David              4
4      Jack       3             3          Paul               4
5      Daniel     3             3          Paul               4

(10 row(s) affected)
2 голосов
/ 10 ноября 2012

Существует возможность избежать повторения в запросах просмотра дерева. Вы можете добавить столбец «Путь» в дерево категорий. Он должен содержать идентификаторы предков каждого элемента, разделенные нечисловым символом (например, косой чертой).

Например, путь вашей категории "ID = 4" будет выглядеть так: "/ 1/2/3 /" Теперь, когда вы присоединяете свою таблицу объявлений к категориям, вам нужно сделать следующее:

select * from ads_table 
inner join cat_table on cat_table.ID = ads_table.category_ID
where cat_table.Path like '/1/%'

И это ваш запрос.

Подробнее об этом можно прочитать в моем сообщении в блоге

1 голос
/ 24 ноября 2010

Вы знакомы с общими табличными выражениями в SQL Server?Одно из многих применений CTE - это рекурсивные запросы.

Ниже приведена одна из лучших статей, которые я нашел по этому вопросу:

http://www.4guysfromrolla.com/webtech/071906-1.shtml

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