Может быть так: вы получаете первый элемент каждой категории и используете его в качестве идентификатора.
Это:
select c.value('./@value', 'varchar(10)') as "ItemValue",
c.value('../item[1]/@value', 'varchar(10)') as "CategoryNumber"
from @x.nodes('//item') as t(c)
Возвращает:
Item Value | CategoryNumber
---------------------------
north | north
south | north
east | north
west | north
red | red
green | red
blue | red
А потом просто
select c.value('./@value', 'varchar(10)') as "ItemValue",
RANK() OVER (ORDER BY c.value('../item[1]/@value', 'varchar(10)')) as "CategoryNumber"
from @x.nodes('//item') as t(c)
Однако возвращается:
Item Value | CategoryNumber
---------------------------
north | 1
south | 1
east | 1
west | 1
red | 5
green | 5
blue | 5
Но это все еще на шаг впереди.