Sql Server 按树形结构排序查询表记录


-- with一个临时表(括号中是你要查询的列名)
with temp(ID,PID,Name,te,curLevel)
as
(
--1:初始查询(这里的ParentAddressBookId is null 在我的数据中是最底层的根节点)
select AddressBookId,ParentAddressBookId,AddressBookName,CAST(AddressBookName AS nvarchar(MAX)) AS name,1 as level from dbo.PersonalAddressBook 
where ParentAddressBookId is null     
union all
--2:递归条件
select a.AddressBookId,a.ParentAddressBookId,a.AddressBookName, cast(replicate(' ',len(b.te))+'|_'+a.AddressBookName as nvarchar(MAX)) as TE,b.curLevel+1 
from PersonalAddressBook a   --3:这里的临时表和原始数据表都必须使用别名,不然递归的时候不知道查询的是那个表的列
inner join
temp b
on ( a.ParentAddressBookId=b.ID)  --这个关联关系很重要,一定要理解一下谁是谁的父节点
)
select * from temp --order by ID  --4:递归完成后 一定不要少了这句查询语句 否则会报错

现在的问题是,排序会乱,。。。。。

然后找到一个周大神的解决方案:

--PersonalAddressBook  表名
--OrderNumber 表内排序,没有 使用 select 1 取代
--AddressBookId ID
--ParentAddressBookId 父ID
--解决树层次多,层次内个数多的问题。
--理论上支持几百层,层内数万以上的结构。
--16W行数结构1分钟多,3000行数就 1秒,4000行1秒,5000行3秒 7000行 5秒左右 (数据库生成树结构时间)
--进行树形结构排序
--试用自行替换字段
 WITH StepCTE1
AS
(--(这里lev 和 表里面treelevel无关,重新设定层级了。)
select AddressBookId,AddressBookName,CAST(AddressBookName AS nvarchar(MAX)) AS name,ParentAddressBookId,1 as Lev, convert(int,ROW_NUMBER() OVER(ORDER BY (OrderNumber))) as t1,
0 as t2,0 as t3,0 as t4, 0 as t5,  0 as t6, 0 as t7, 0 as t8, 0 as t9, 0 as t10
from PersonalAddressBook where ParentAddressBookId is null --这里是入口层 如果有限制,这里增加其他 条件
UNION ALL
select t.AddressBookId,t.AddressBookName,cast(replicate(' ',CTE.Lev*4)+'|_'+t.AddressBookName as nvarchar(MAX)) as name,t.ParentAddressBookId ,CTE.Lev + 1,
	CTE.t1  as t1,
    case when CTE.[Lev] = 1 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t2 end as t2,
    case when CTE.[Lev] = 2 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t3  end as t3,
    case when CTE.[Lev] = 3 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t4  end as t4,
     case when CTE.[Lev] = 4 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t5  end as t5,
     case when CTE.[Lev] = 5 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t6  end as t6,
     case when CTE.[Lev] = 6 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t7  end as t7,
     case when CTE.[Lev] = 7 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t8  end as t8,
     case when CTE.[Lev] = 8 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t9  end as t9,
     case when CTE.[Lev] = 9 then convert(int,ROW_NUMBER() OVER(ORDER BY (t.OrderNumber)))
    else CTE.t10  end as t10
    from PersonalAddressBook t INNER JOIN StepCTE1 CTE   ON T.ParentAddressBookId = CTE.AddressBookId
--如果有限制,这里增加 where 条件

)
SELECT
  AddressBookId, ParentAddressBookId, AddressBookName,name, Lev, t1,t2,t3,t4,t5,t6,t7,t8,t9,t10
  FROM 
  StepCTE1
  ORDER BY
  t1,t2,t3,t4,t5,t6,t7,t8,t9,t10


但是好像排序写死了,好多t0,t1,t2.......难道有几层要写几层,容我再找找资料去。。。大神应该还有别的解决办法

发布了18 篇原创文章 · 获赞 16 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/liangpingguo/article/details/84632153
今日推荐