Таблица иерархического дерева (sql) Запрос из одной таблицы - PullRequest
0 голосов
/ 11 декабря 2019

Ситуация

У меня есть таблица, содержащая номера деталей в иерархической древовидной структуре. partno является родителем, а partno_item является дочерним, однако это изменяется, так как дочерний элемент может стать родительским для другой части и переместиться к partno столбец.

Таблица выглядит в основном следующим образом (я также пропустил некоторые столбцы, первый из которых содержит внутренний уникальный ключ)

╔═════════╦═════════════╗
║ partno  ║ partno_item ║
╠═════════╬═════════════╣
║ 123-01  ║ 1234-01     ║
║ 123-01  ║ 1234-02     ║
║ 123-01  ║ 1234-03     ║
║ 1234-03 ║ 1234-04     ║
║ 1234-04 ║ 1234-05     ║
╚═════════╩═════════════╝

Я хотел бы найти определенную часть и показать всех ее детей и внуков. В этом случае я ищу 123-01, и я хотел бы получить результат, подобный этому. Желательно с дополнительным столбцом, который показывает уровень в иерархии

╔═════════════╦═══════╗
║ partno_item ║ level ║
╠═════════════╬═══════╣
║ 1234-01     ║     1 ║
║ 1234-02     ║     1 ║
║ 1234-03     ║     1 ║
║ 1234-04     ║     2 ║
║ 1234-05     ║     3 ║
╚═════════════╩═══════╝

Как я могу добиться этого с помощью запроса?


Обновление: СУБД - это Sybase ASE

1 Ответ

1 голос
/ 12 декабря 2019

Эта процедура getItems должна делать то, что вы хотите: P См. Код

Результат выглядит следующим образом:

partno  partno_item
123-01  1234-01
123-01  1234-02
123-01  1234-03
1234-03 1234-04
1234-04 1234-05
123-02  1234-06
partno_item     lvl
1234-01 1
1234-02 1
1234-03 1
1234-04 2
1234-05 3

Редактировать: Перенес код в ответ

-- src table
create table #src(
  partno      varchar(10),
  partno_item varchar(10)
)

insert #src(partno, partno_item) values('123-01', '1234-01')
insert #src(partno, partno_item) values('123-01', '1234-02')
insert #src(partno, partno_item) values('123-01', '1234-03')
insert #src(partno, partno_item) values('1234-03', '1234-04')
insert #src(partno, partno_item) values('1234-04', '1234-05')
insert #src(partno, partno_item) values('123-02', '1234-06')

select * from #src
go


-- get items
create procedure getItems
  @partno     varchar(10)
as
  declare
    @lvl      int

  select @lvl = 1

  -- tmp table
  create table #tmp(
    partno_item varchar(10),
    lvl         int
  )

  if exists(
    select partno from #src where (partno = @partno)
  ) begin
    insert #tmp(partno_item, lvl)
    select distinct partno_item, @lvl from #src where (partno = @partno)

    while exists(
      select distinct s.partno_item
      from #src s, #tmp t
      where (t.lvl = @lvl)
        and (t.partno_item = s.partno)
    ) begin
      select @lvl = @lvl + 1    -- increase lvl

      insert #tmp(partno_item, lvl)
      select distinct s.partno_item, @lvl
      from #src s, #tmp t
      where (t.lvl = @lvl - 1)
        and (t.partno_item = s.partno)
    end
  end

  select * from #tmp
  truncate table #tmp
  drop table #tmp
go


-- exec
exec getItems '123-01'
go


truncate table #src
drop table #src
drop procedure getItems
go
...