我正试图从SqlServer表中获取叶子节点,如下所示:
Id |Text
-----------------
01 |dasdasd
01.01 |asaasa
01.02 |dasdd
01.02.01|ddada
02 |sdad
作为结果,我希望此表仅具有叶节点...
Id |Text
----------------
01.01 |asaasa
01.02.01|ddada
02 |sdad
感谢帮助
答案 0 :(得分:0)
数据:
drop table if exists #test
create table #test (id varchar(20), text varchar(30))
insert #test values ('01', 'dasdasd')
, ('01.01', 'asaasa')
, ('01.02', 'dasdd')
, ('01.02.01', 'ddada')
, ('02', 'sdad')
查询:
select id, text from #test t1
cross apply (
select count(*) cnt from #test t2 where t2.id like t1.id + '%'
) calc
where calc.cnt = 1
输出:
id text
01.01 asaasa
01.02.01 ddada
02 sdad
答案 1 :(得分:0)
您可以利用Id
的层次结构表示来查找没有其他以其ID开头的行的行:
create table #table1 (id varchar(40) primary key,Text varchar(200))
insert into #table1 (id,text)
values
('01','dasdasd'),
('01.01','asaasa'),
('01.02','dasdd'),
('01.02.01','ddada'),
('02','sdad')
SELECT t1.*,t2.*
FROM #table1 t1 LEFT OUTER JOIN #table1 t2
ON t2.id LIKE t1.id + '%'
AND t1.id!=t2.id
WHERE t2.id IS NULL
t2.id like t1.id + '%'
将找到t1
的后代,而t1.id!=t2.id
确保同一行不匹配。最后t2.id is null
放弃所有匹配项,仅留下叶子行。结果是:
id Text
01.01 asaasa
01.02.01 ddada
02 sdad
最好用实际的hierarchyid
列替换层次结构字符串。首先,该字符串每个级别最多只能使用99个节点。添加更多节点将需要重写所有密钥。其次,需要使用字符串操作来查找叶子,祖先,级别等。
等效表如下所示:
create table #table2 (id hierarchyid primary key,Text varchar(200))
insert into #table2 (id,text)
values
('/1/','dasdasd'),
('/1/1/','asaasa'),
('/1/2/','dasdd'),
('/1/2/1/','ddada'),
('/2/','sdad')
使用GetAncestor()
函数而不是LIKE ..
来获取叶子节点的方式与以前类似:
SELECT t1.Id.ToString(), t1.Text
FROM #table2 t1 LEFT OUTER JOIN #table2 t2
ON t1.Id = t2.Id.GetAncestor(1)
WHERE t2.Id IS NULL;
添加节点级别是微不足道的,甚至不会影响执行计划。不过,在上一个查询中执行相同的操作将需要对ID
字段中的点进行计数:
SELECT t1.Id.ToString() As ID, t1.Id.GetLevel() As Level,t1.Text
FROM #table2 t1 LEFT OUTER JOIN #table2 t2
ON t1.Id = t2.Id.GetAncestor(1)
WHERE t2.Id IS NULL;
这次的结果是:
ID Level Text
/1/1/ 2 asaasa
/1/2/1/ 3 ddada
/2/ 1 sdad