объединение всех родительских элементов в многоуровневую или древовидную структуру

#sql #sql-server

#sql #sql-сервер

Вопрос:

У меня есть 2 таблицы

 1. parent table and 2. Child Table
  

Значение родительской таблицы

 Pid parent_name
1  A 
2  B
3  D
4  H
5  J
  

Значение дочерней таблицы

 Chid Pid child_name
1     1   B
2     1   C
3     1   D
4     2   F
5     2   G
6     3   H
7     3   I
8     4   J
9     4   K
10    5   L
  

когда я введу ввод A, я получу вывод в виде

 Pid
B
D
H
J
  

когда я введу ввод D, я получу вывод в виде

 Pid
H
J
  

Похоже на древовидную структуру, когда я даю родительское имя, результатом будут все дочерние элементы, внуки, внучатые дочерние элементы….
все родительские элементы, имеющие дочерний

Ответ №1:

Вам нужно использовать рекурсивный CTE для вашей цели.

  DECLARE @Id varchar(10)='your_pid' 
;WITH cte AS 
 (
  SELECT b.pid, b.chid, b.parent_name
  FROM parent a inner join child b on b.pid= a.pid
  WHERE b.pid = @Id
  UNION ALL
  SELECT b.pid
  FROM parent a inner join child b on b.pid= a.pid
  inner join cte on cte.pid= b.chid
  WHERE b.pid = @Id  )
  SELECT parent_name
  FROM cte
  

Ответ №2:

Я полагаю, вам нужно будет сохранить родительские дочерние записи в одной таблице следующим образом:

 1   NULL    A
2   1   B
3   1   C
4   1   D
5   2   F
6   2   G
7   4   H
8   4   I
9   7   J
10  7   K
11  9   L
  

Затем вы можете запросить данные следующим образом:

 WITH T (id, pid, name) AS (
    SELECT 1, NULL, 'A'
    UNION ALL
    SELECT 2, 1, 'B'
    UNION ALL
    SELECT 3, 1, 'C'
    UNION ALL
    SELECT 4, 1, 'D'
    UNION ALL
    SELECT 5, 2, 'F'
    UNION ALL
    SELECT 6, 2, 'G'
    UNION ALL
    SELECT 7, 4, 'H'
    UNION ALL
    SELECT 8, 4, 'I'
    UNION ALL
    SELECT 9, 7, 'J'
    UNION ALL
    SELECT 10, 7, 'K'
    UNION ALL
    SELECT 11, 9, 'L'
), U AS (
    SELECT B.* FROM T A JOIN T B ON B.pid = A.id JOIN T C ON C.pid = B.id WHERE A.name = 'A'
    UNION ALL
    SELECT P.* FROM T P JOIN U Q ON Q.id = P.pid JOIN T R ON R.pid = P.id
)
SELECT DISTINCT name FROM U
  

Например, если ваша таблица называется «tbl», то:

 WITH T (id, pid, name) AS (
    SELECT id, pid, name FROM tbl
), U AS (
    SELECT B.* FROM T A JOIN T B ON B.pid = A.id JOIN T C ON C.pid = B.id WHERE A.name = 'A'
    UNION ALL
    SELECT P.* FROM T P JOIN U Q ON Q.id = P.pid JOIN T R ON R.pid = P.id
)
SELECT DISTINCT name FROM U