Запрос T-SQL.Выбор "ветки дерева" из таблицы - PullRequest
4 голосов
/ 12 марта 2012

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

name  id  manager_id
____________________
adam  1   Null
nick  2   1
sten  3   1
iren  4   3
john  5   2
steve 6   3

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

steve 6 3
sten  3 1
adam  1 Null

Как это можно сделать? (пока не нужно избегать петель)

Ответы [ 6 ]

1 голос
/ 12 марта 2012

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

USE [temp]
GO
/****** Object:  StoredProcedure [dbo].[temp1]    Script Date: 03/12/2012 16:53:40 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[temp1]

@id INT

AS

WITH DirectReports (name, id, manager_id)
AS
(
-- Anchor member definition

SELECT t.name, t.id, t.manager_id
FROM Temp AS t
WHERE t.id = @id

UNION ALL

-- Recursive member definition

SELECT t.name, t.id, t.manager_id
FROM Temp AS t INNER JOIN DirectReports AS d
ON t.id = d.manager_id
)

-- Statement that executes the CTE
SELECT name, id, manager_id
FROM DirectReports

GO
1 голос
/ 12 марта 2012
declare @T table
(
  name varchar(10),
  id int,
  manager_id int
)
insert into @T values
('adam',  1,   Null),
('nick',  2,   1),
('sten',  3,   1),
('iren',  4,   3),
('john',  5,   2),
('steve', 6,   3)

declare @id int
set @id = 6

;with C as
(
  select T.name,
         T.id,
         T.manager_id
  from @T as T
  where T.id = @id
  union all
  select T.name,
         T.id,
         T.manager_id
  from @T as T
    inner join C
      on T.id = C.manager_id
)
select name,
       id,
       manager_id
from C
1 голос
/ 12 марта 2012

Если ваша СУБД поддерживает cte, то примерно так:

Данные испытаний

DECLARE @tbl TABLE(name VARCHAR(100),id INT, manager_id INT)

INSERT INTO @tbl
VALUES
    ('adam',1,Null),
    ('nick',2,1),
    ('sten',3,1),
    ('iren',4,3),
    ('john',5,2),
    ('steve',6,3)

Запрос

DECLARE @id INT=6--Steve
;WITH CTE(name,id,manager_id)
AS
(
    SELECT
        tbl.name,
        tbl.id,
        tbl.manager_id
    FROM
        @tbl AS tbl
    WHERE
        tbl.id=@id
    UNION ALL
    SELECT
        tbl.name,
        tbl.id,
        tbl.manager_id
    FROM
        @tbl AS tbl
        JOIN CTE
            ON CTE.manager_id=tbl.id
)
SELECT
    *
FROM
    CTE
1 голос
/ 12 марта 2012

Начиная с SQL 2005, вы можете использовать рекурсивный CTE , как показано ниже:

;WITH Managers AS
(
SELECT name, id, manager_id, 1 AS Level 
FROM YourTable
WHERE id = 6
UNION ALL
SELECT t.name, t.id, t.manager_id, m.Level + 1
FROM YourTable t
    JOIN Managers m ON t.id = m.manager_id
)
SELECT * FROM Managers ORDER BY Level DESC

Или, начиная с SQL 2008, вы можете использовать другой подход, используя новый тип данных HIERARCHYID , который представляет собой новый способ представления иерархических данных.

1 голос
/ 12 марта 2012

Нечто подобное должно сработать!

create table #result (
  ident identity
  name varchar(30),
  id int,
  manager_id int
)


declare @name varchar(30), @name2 varchar(30)
declare @id int, @manager_id int, @manager_id2 int

select @name = name, @id = id, @manager_id = manager_id from tablename where name = 'steve'



while(@manager_id <> null)
begin
  select @manager_id2 = @manager_id

  insert into #result(@name, @id, @manager_id)

  select @name = name, @id = id, @manager_id = manager_id from tablename where id = @manager_id2    
end

insert into #result(@name, @id, @manager_id)

select name, id, manager_id from #result order by ident desc


drop table #result
1 голос
/ 12 марта 2012

Вы можете использовать TSQL Common Table Expressions CTE

Используйте эту ссылку ниже для справки.

http://blog.namwarrizvi.com/?p=25

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...