Вернуть иерархию без создания каких-либо представлений или таблиц? - PullRequest
1 голос
/ 05 сентября 2011

У меня есть таблица со столбцами и данными следующим образом:

Table1
ID  Name    PID
A1  Apple   P1
B1  Book    A1
B2  Brook   A1
C1  Cat     B1
C2  Cook    B1
C3  Car     B1
D1  Dog     B2
D2  Doll    B2
E1  Egg     C1

Я хочу получить следующие результаты:

ID  Name                    Depth
B1  Apple\Book              2
C1  Apple\Book\Cat          3
E1  Apple\Book\Cat\Egg      4
C2  Apple\Book\Cook         3
C3  Apple\Book\Car          3
B2  Apple\Brook             2
D1  Apple\Brook\Dog         3
D2  Apple\Brook\Doll        3

Отношение состоит в том, что строка является дочерним элементом другогострока, если PID этой строки равна ID родительской строки.

Apple - основа.Таким образом, первое утверждение будет выглядеть примерно так:

Select ID, Name, 2 from Table1 where PID=(select ID from Table1 where Name='Apple');

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

Ответы [ 3 ]

2 голосов
/ 05 сентября 2011

Я не знаю, есть ли элегантный способ получить точный порядок, который вы перечислили, но вот один из подходов с рекурсивным CTE:

;WITH cte AS
(
    SELECT ID, Name, Depth = 1
        FROM dbo.Table1 
        WHERE Name = 'Apple'
    UNION ALL
    SELECT t.ID, t.Name, Depth = cte.Depth + 1
        FROM cte 
        INNER JOIN dbo.Table1 AS t
        ON t.PID = cte.ID
)
SELECT ID, Name, Depth
FROM cte
WHERE Depth > 1;
1 голос
/ 05 сентября 2011
declare @Table1 table
(
  ID varchar(2),
  Name varchar(10),
  PID varchar(2)
)

insert into @Table1 values  
('A1',  'Apple',   'P1'),
('B1',  'Book',    'A1'),
('B2',  'Brook',   'A1'),
('C1',  'Cat',     'B1'),
('C2',  'Cook',    'B1'),
('C3',  'Car',     'B1'),
('D1',  'Dog',     'B2'),
('D2',  'Doll',    'B2'),
('E1',  'Egg',     'C1')

;with C as
(
  select T.ID,
         cast(T.Name as varchar(max)) as Name,
         1 as Depth
  from @Table1 as T
  where T.Name = 'Apple'
  union all
  select T.ID,
         cast(C.Name+'\'+T.Name as varchar(max)),
         C.Depth + 1
  from @Table1 as T
    inner join C
      on T.PID = C.ID
)
select C.ID,
       C.Name,
       C.Depth
from C
where C.Depth > 1
order by C.Name

Редактировать Без Apple.

;with C as
(
  select T.ID,
         cast(T.Name as varchar(max)) as Name,
         1 as Depth
  from @Table1 as T
    inner join @Table1 as TP
      on T.PID = TP.ID
  where TP.Name = 'Apple'
  union all
  select T.ID,
         cast(C.Name+'\'+T.Name as varchar(max)),
         C.Depth + 1
  from @Table1 as T
    inner join C
      on T.PID = C.ID
)
select C.ID,
       C.Name,
       C.Depth
from C
order by C.Name
0 голосов
/ 05 сентября 2011

Вот запрос, который я придумал на PostgreSQL.У меня нет SQL Server, поэтому я не могу проверить, но Google заставил меня поверить, что эта структура запросов будет работать и на SQL Server.,Обратите внимание, что PostgreSQL требует WITH RECURSIVE при объявлении общего табличного выражения, которое ссылается на себя.Это и пример данных, единственные различия между двумя запросами:

$ WITH Table1(ID, Name, PID) AS (VALUES
$     ('A1', 'Apple', 'P1'),
$     ('B1', 'Book',  'A1'),
$     ('B2', 'Brook', 'A1'),
$     ('C1', 'Cat',   'B1'),
$     ('C2', 'Cook',  'B1'),
$     ('C3', 'Car',   'B1'),
$     ('D1', 'Dog',   'B2'),
$     ('D2', 'Doll',  'B2'),
$     ('E1', 'Egg',   'C1')
$ )
$ SELECT t1.*, (
$     WITH RECURSIVE q AS (
$         SELECT t2.*
$         FROM Table1 AS t2
$         WHERE t2.ID = t1.ID
$            OR (t1.ID IS NULL AND t2.ID IS NULL)
$
$         UNION ALL
$
$         SELECT t3.*
$         FROM Table1 AS t3
$         JOIN q
$         ON t3.ID = q.PID
$         AND t3.ID <> 'P1'
$     )
$     SELECT COUNT(q.ID)
$     FROM q
$ ) AS depth
$ FROM Table1 AS t1;
 id | name  | pid | depth
----+-------+-----+-------
 A1 | Apple | P1  |     1
 B1 | Book  | A1  |     2
 B2 | Brook | A1  |     2
 C1 | Cat   | B1  |     3
 C2 | Cook  | B1  |     3
 C3 | Car   | B1  |     3
 D1 | Dog   | B2  |     3
 D2 | Doll  | B2  |     3
 E1 | Egg   | C1  |     4
(9 rows)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...