Рекурсивный запрос SQL Server 2008

FromID               ToID     
--------------    ----------    
   1              2               
   2              3                 
   3              4                 
   5              6                
   6              7                
   9              10

Я хотел бы использовать рекурсивный запрос в SQL Server 2008 для создания вывода как

FromID                Path
1                     1,2,3,4
5                     5,6,7                                          
9                     9,10

Я пытаюсь построить инструкцию SQL, используя ссылки на онлайн-примеры, как показано ниже.

;WITH items AS (
  SELECT FromID
  , CAST(FromID AS VARCHAR(255)) AS Path
  FROM tablex
  UNION ALL
  SELECT i.FromID
  , CAST(Path + '.' + CAST(i.FromID AS VARCHAR(255)) AS VARCHAR(255)) AS Path
  FROM tablex i
  INNER JOIN items itms ON itms.FromID = i.ToID
)
SELECT * 
FROM items 
ORDER BY Path

Однако выше не работает. Есть идеи?

sql-server-2008,recursive-query,

1

Ответов: 1


1

Мне не совсем понятно, почему ваш ожидаемый результат - это то, что есть. Путь от 6-10 - это не полный путь к 10: этот путь начинается с ID 5. Я написал пример, который выводит полный путь, чтобы проиллюстрировать, как вы это делаете. Если вы действительно хотите, чтобы он начинался с 6 по какой-то причине, пожалуйста, четко укажите правило, определяющее, какие узлы должны появляться в качестве отправных точек в результирующем наборе.

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

declare @TableX table (FromID int, ToID int);
insert @TableX values (1, 2), (2, 3), (3, 4), (5, 6), (6, 7), (6, 9), (9, 10);

with PathCTE as
(
    -- BASE CASE
    -- Any ID that appears as a "to" but not a "from" is the endpoint of a path. This
    -- query captures the ID that leads directly to that endpoint, plus the path
    -- represented by that one row in the table.
    select
        X1.FromID,
        [Path] = convert(varchar(max), X1.FromID) + ',' + convert(varchar(max), X1.ToID)
    from
        @TableX X1
    where
        not exists (select 1 from @TableX X2 where X2.FromID = X1.ToID)

    union all

    -- RECURSIVE CASE
    -- For every path previously identified, look for another record in @TableX that
    -- leads to its starting point and prepend that record's from ID to the overall path.
    select
        X.FromID,
        [Path] = convert(varchar(max), X.FromID) + ',' + PathCTE.[Path]
    from
        PathCTE
        inner join @TableX X on PathCTE.FromID = X.ToID
)

-- Any ID that appears as a "from" but not a "to" is the starting point of one or more
-- paths, so we get all results beginning at one of those points. All other output from
-- PathCTE is partial paths, which we can ignore.
select * 
from 
    PathCTE 
where
    not exists (select 1 from @TableX X where PathCTE.FromID = X.ToID)
order by
    FromID, [Path];

Вывод:

FromID   Path
1        1,2,3,4
5        5,6,7
5        5,6,9,10
SQL-сервер 2008, рекурсивный-запрос,
Похожие вопросы