在SQL中构造树

时间:2013-12-13 09:02:54

标签: sql linq-to-sql

我有一个这样的表,有一些行。

ID | REfID | Name
------------------
1  |       |  name1    
2  |   5   |  name2
3  |   4   |  name3
4  |   1   |  name4
5  |   3   |  name2

如何根据ID和RefID查询SQL中子进程的子进程和子进程。例如,当我给出ID = 5时,

它应该返回行(ID)3,4,1

我创建一个查询使用LINQ,它工作正常。

List<Employee> empList = new List<Employee>()
            {
                new Employee() { ID=1,Name = "Name1" },
                 new Employee() { ID=2,Name = "Name1" ,REFID = 5},
                  new Employee() { ID=3,Name = "Name1" ,REFID = 4},
                  new Employee() { ID=4,Name = "Name1" ,REFID = 1},
                   new Employee() { ID=5,Name = "Name1" ,REFID = 3},

            };

        // 5 = >3 => 4 => 1.

        Dictionary<int, Employee> employeeByID = empList.ToDictionary(x => x.ID);
        List<Employee> result = new List<Employee>();
        this.findChild(employeeByID[5], employeeByID, ref result);

public void findChild(Employee emp, Dictionary<int, Employee> source,ref List<Employee> result)
        {
            result.Add(emp);

            if (source.ContainsKey(emp.REFID))
            {
                Employee child = source[emp.REFID];
                this.findChild(child ,source, ref result);

            }
        }

我需要创建一个等效的SQL查询。如何存档?

1 个答案:

答案 0 :(得分:1)

它还没有解决你的问题,但给你一些工作。使用递归CTE,您可以跟踪所有记录的子父关系(我假设您使用SQL Server):

drop table #temp
GO
select 
    *
into #temp
from (
    select 1 as id, null as refid,  'name1' as name    union all
    select 2, 5, 'name2' union all
    select 3, 4, 'name3' union all
    select 4, 1, 'name4' union all
    select 5, 3, 'name2'
) x
GO

;with cte as (
    select 
        id, refid, name, 
        idpath  = cast(id as varchar(255))
    from #temp 
    where 1=1
        and refid is null
union all
    select 
        t.id, t.refid, t.name, 
        idpath  = cast(c.idpath+'|'+cast(t.id as char(1)) as varchar(255))
    from #temp t 
    join cte c
        on c.id=t.refid
)

select 
    * 
from cte