… fiddle
select
cast('<x>AB</x>
<x>AB</x>
<x>AB</x>
<x>AC</x>
<x>AB</x>' as xml).query('
for $v in x
let $n := x[. >> $v][1]
where not($v/text() = $n/text())
return (string($v/text()[1]))
')
fiddle
select stuff(
cast('<x>AB</x>
<x>AB</x>
<x>AB</x>
<x>AC</x>
<x>AB</x>' as xml).query('
for $v in x/text()
let $n := x[. >> $v][1]/text()
where not($v = $n)
return text{concat(" | ", $v)}
').value('.', 'nvarchar(max)'), 1, 3, '')
select stuff(
cast('<x>AB</x>
<x>AB</x>
<x>AB</x>
<x></x>
<x></x>
<x></x>
<x></x>
<x></x>
<x></x>
<x>AC</x>
<x>AB</x>' as xml).query('
for $v in x
let $n := x[. >> $v][1]
where not($v/text()= $n/text() or (empty($v/text()) and empty($n/text())))
return text{concat(" | ", $v/text()[1])}
').value('.', 'nvarchar(max)'), 1, 3, '')
a faster approach with the same idea as in the xquery: find the last value of a sequence. fiddle
select s.hierarchy
from t
cross apply
(
select string_agg(isnull(x, ''), ' | ') within group(order by rn) as hierarchy
from
(
select rn, x, lead(x) over(order by rn) as n
from
(
select row_number() over(order by n.x) as rn, n.x.value('text()[1]', 'varchar(20)') as x
from t.TheParts.nodes('x') as n(x)
) as d
) as l
where isnull(x, char(1)) <> isnull(n, char(1))
) as s