; with Q as ( select rowguid, cast(null as nvarchar(100)) as s, rowguid as r from RTbl union all select rowguid, substring(r, i, n), substring(r, i + n, len(r)) from Q cross apply (values (patindex('%[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]%', r), patindex('%[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]%', r))) t1(i1, i2) cross apply (values (case when i2 > 0 and i2 <= i1 then 2 when i1 > 0 then 1 end)) t2(k) cross apply (values (case k when 1 then i1 when 2 then i2 end, case k when 1 then 4 when 2 then 5 end)) t3(i, n) where k is not null ) select rowguid, string_agg(s, ';') as val2 from Q where s is not null group by rowguid