sql-server-2005 – SQL查询:分层合并
发布时间:2020-12-12 06:42:09 所属栏目:MsSql教程 来源:网络整理
导读:我有一个定义层次结构的表: Create Table [example] ( id Integer Not Null Primary Key,parentID Integer Null,largeData1 nVarChar(max) Null,largeData2 nVarChar(max) Null); -- largeData3...n also existInsert Into [example] (id,parentID,largeData
我有一个定义层次结构的表:
Create Table [example] (
id Integer Not Null Primary Key,parentID Integer Null,largeData1 nVarChar(max) Null,largeData2 nVarChar(max) Null);
-- largeData3...n also exist
Insert Into [example] (id,parentID,largeData1,largeData2)
Select 1,null,'blah blah blah',null Union
Select 2,1,null Union
Select 3,'foo bar foobar',null Union
Select 4,3,'lorem ipsum' Union
Select 5,4,null;
此数据的层次结构图: 我想编写一个查询,它将返回任何给定[id]值的单行.该行应包含该行的[id]和[parentID]信息.它还应包含[largeData1 … n]字段.但是,如果largeData字段为null,则它应该遍历层次结构,直到遇到该字段的非null值.简而言之,它应该像coalesce函数一样工作,除了行的层次结构而不是一组列. 例: 其中[id] = 1: id: 1 parentID: null largeData1: blah blah blah largeData2: null 其中[id] = 2 id: 1 parentID: 1 largeData1: blah blah blah largeData2: null 其中[id] = 3 id: 3 parentID: 1 largeData1: foo bar foobar largeData2: null 其中[id] = 4 id: 4 parentID: 3 largeData1: foo bar foobar largeData2: lorem ipsum 其中[id] = 5 id: 5 parentID: 4 largeData1: foo bar foobar largeData2: lorem ipsum 到目前为止,我有这个: Declare @id Integer; Set @id = 5;
With heirarchy
(id,largeData2,[level])
As (
Select id,1 As [level]
From example
Where id = @id
Union All
Select parent.id,parent.parentID,parent.largeData1,parent.largeData2,child.[level] + 1 As [level]
From example As parent
Inner Join heirarchy As child
On parent.id = child.parentID)
Select id,(Select top 1 largeData1
From heirarchy
Where largeData1 Is Not Null
Order By [level] Asc) As largeData1,(Select top 1 largeData2
From heirarchy
Where largeData2 Is Not Null
Order By [level] Asc) As largeData2
From example
Where [id] = @id;
这将返回我要查找的结果.但是,根据查询计划,它会为我撤回的每个largeData字段单独传递层次结构. 我怎样才能提高效率呢? 这显然是更复杂问题的简化版本.最终查询将以XML格式返回数据,因此涉及FOR XML子句的任何解决方案都非常好. 我可以为此创建一个CLR聚合函数,如果这样做会有所帮助.我还没有探索过这条路线. 解决方法我想出了这个:DECLARE @Id int
SET @Id = 5
;WITH cte (Id,ParentId,SaveParentId,LargeData1,LargeData2)
as (-- The "anchor",your target Id
select
ex.Id,ex.ParentId,ex.ParentId SaveParentId -- Not changed throughout the CTE,ex.LargeData1,ex.LargeData2
from Example ex
where ex.Id = @Id
union all select
cte.Id,cte.SaveParentId -- Not changed throughout the CTE
-- These next are only "reset" if they are null and a not-null
-- value was found at this level,isnull(ex.LargeData1,cte.LargeData2),isnull(ex.LargeData2,cte.LargeData2)
from Example ex
inner join cte
on cte.ParentId = ex.Id)
select
Id,SaveParentId ParentId,max(LargeData1) LargeData1,max(LargeData2) LargeData2
from cte
group by Id,SaveParentId
基本上,从目标节点开始并向上走树,在找到它们时将空列替换为非空值. (抱歉,我周末不做XML.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
