2015-02-03 3 views
0

У меня есть таблица, держащего иерархическую структуру так что в основном она имеет 3 колонки, как:Выберите из иерархии на основе диапазона идентификаторов

enter image description here

То, что я хочу, чтобы выбрать из этой таблицы, в диапазоне идентификаторы, например:

Id IN (1,4,8,18) 

что приводит к:

enter image description here

Другими словами, ряд должен прийти в набор результатов со всеми его родителями и детьми.

Как я могу решить эту проблему?
Заранее спасибо

ответ

1

Вы можете сделать это с помощью КТР:

DECLARE @t TABLE (ID INT, ParentID INT) 

INSERT INTO @t 
VALUES (1, NULL), 
     (2, 1), 
     (3, 2), 
     (4, 3), 
     (6, NULL), 
     (7, 6), 
     (8, 7), 
     (9, 8), 
     (10, 9), 
     (11, 10), 
     (13, NULL), 
     (14, 13), 
     (15, 14), 
     (17, NULL), 
     (18, 17), 
     (19, 18), 
     (20, 19); 

WITH ctep 
      AS (SELECT * 
       FROM  @t 
       WHERE ID IN (1, 4, 8, 18) 
       UNION ALL 
       SELECT t.* 
       FROM  @t t 
         JOIN ctep ON t.ParentID = ctep.ID 
      ), 
     ctec 
      AS (SELECT * 
       FROM  @t 
       WHERE ID IN (1, 4, 8, 18) 
       UNION ALL 
       SELECT t.* 
       FROM  @t t 
         JOIN ctec ON t.ID = ctec.ParentID 
      ) 
    SELECT * FROM ctep 
    UNION 
    SELECT * FROM ctec 

Вот 2, CTE, для получения родителей и Чайлдс. Наконец, вы объединяете эти 2 результата, чтобы получить отдельные строки.

У меня была небольшая ошибка. Под редакцией ...

0

Вы можете использовать рекурсивное общее табличное выражение (CTE). Он очень хорош в таких задачах. Ниже я предположил, что tbl - это имя вашей таблицы.

WITH UserCTE AS 
(

SELECT Id, name, ParentId 
FROM tbl 
WHERE Id in (1,4,8,18) 

UNION ALL 

SELECT P.Id, P.name, P.ParentId 
FROM UserCTE AS C --- C for child 
JOIN tbl AS P --- P for parent 
ON C.ParentId = P.Id 

) 
SELECT Id, name, ParentId 
FROM UserCTE; 

Вы также можете попробовать использовать

SELECT DISTINCT Id, name, ParentId 
FROM UserCTE; 

, если вы заметили, что некоторые записи возвращаются более чем один раз.

+0

хорошее решение ... –

+0

Это не будет работать для детей ... (1,3,8,18) не выбирает 4, а 4 является ребенком 3. –

+0

это решение также не выталкивает детей –

1

Сплит ваша задача на два этапа

  1. Найти самый верхний родитель
  2. Найти все потомкам

    WITH ToTopParent AS 
    (
        SELECT Id, ParentId 
        FROM yourTable 
        WHERE Id IN (1,4,8,18) 
    
        UNION ALL 
    
        SELECT T.Id, T.ParentId 
        FROM ToTopParent TTP 
        JOIN yourTable T ON TTP.ParentId = T.Id 
    ), 
    AllDecedents AS 
    (
        SELECT Id, Name, ParentID 
        FROM yourTable 
        WHERE id IN (SELECT Id FROM ToTopParent WHERE ParentId IS NULL) 
    
        UNION ALL 
    
        SELECT T.Id, T.Name, T.ParentID 
        FROM yourTable T 
        JOIN AllDecedents ON T.ParentId = AllDecedents.Id 
    ) 
    SELECT * FROM AllDecedents 
    
+0

спасибо @qxg. ваше решение работает идеально, но был еще один правильный ответ, который пришел раньше –

Смежные вопросы