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.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |