【问题标题】:T-SQL request. Selecting "tree branch" from the tableT-SQL 请求。从表中选择“树枝”
【发布时间】:2023-03-29 14:52:02
【问题描述】:

我有一张表,其中的记录相互链接

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

我想要一个存储过程,它将为当前工作人员返回一组经理。例如,如果我要求 Steve 的经理查询结果应该是这样的

steve 6 3
sten  3 1
adam  1 Null

怎么做? (暂时不需要避免循环)

【问题讨论】:

  • 您使用的是哪个版本的 SQL Server?
  • @AdaTheDev,MS SQL Server 2008。但如果你能展示旧版本的变体,那就太好了。

标签: sql tsql database-cursor


【解决方案1】:

从 SQL 2005 开始,您可以使用recursive 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 数据类型,这是一种表示分层数据的新方法。

【讨论】:

    【解决方案2】:

    你可以使用TSQLCommon Table ExpressionsCTE

    使用下面的链接作为参考。

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

    【讨论】:

      【解决方案3】:

      这样的事情应该可以解决问题!

      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
      

      【讨论】:

        【解决方案4】:

        如果您的 DBMS 支持 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
        

        【讨论】:

          【解决方案5】:
          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
          

          【讨论】:

            【解决方案6】:

            下面的解决方案使用递归 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
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2015-04-22
              • 1970-01-01
              • 2017-08-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-10-30
              相关资源
              最近更新 更多