Как можно сгладить иерархию категорий в SQL Server 2008? - PullRequest
3 голосов
/ 30 ноября 2011

У меня есть таблица, которая содержит иерархию категорий.Он может иметь любое количество уровней категорий.

Мне нужно отобразить эти категории в простом строковом формате, например:

>>parent>>child1>>subchild>>...

Это пример данных:

Id  Parent  Name
1   NULL    Categories
4   NULL    Instrument
55  NULL    Genre
65  NULL    Geographical Place 
8   1   CLASSICAL
47  1   SOLO INSTRUMENTS
10694   1   STYLES
4521    4   Piano
1137    8   SOLO INSTRUMENTS
1140    8   WALTZES
841 47  PIANO
93328   55  CLASSICAL
93331   55  BLUES
93334   55  CLUB / ELECTRONICA
93339   55  CONTEMPORARY FOLK
93344   55  CHILDREN
94892   65  EUROPE
4180    10694   CLASSICAL - SOLO PIANO
94893   94892   Western & Southern  Europe
94900   94893   France

Ответы [ 2 ]

2 голосов
/ 30 ноября 2011

Возможно, у кого-то есть лучший способ выполнить последнюю часть (избавиться от промежуточных строк), но это поможет вам без жесткого кодирования любых соединений:

declare @Categories table
(
    categoryID int,
    categoryParentID int,
    categoryDesc nvarchar(100)
)
insert into @Categories values
(1,NULL,'Categories'),
(4,NULL,'Instrument'),
(55,NULL,'Genre'),
(65,NULL,'Geographical Place '),
(8,1,'CLASSICAL'),
(47,1,'SOLO INSTRUMENTS'),
(10694,1,'STYLES'),
(4521,4,'Piano'),
(1137,8,'SOLO INSTRUMENTS'),
(1140,8,'WALTZES'),
(841,47,'PIANO'),
(93328,55,'CLASSICAL'),
(93331,55,'BLUES'),
(93334,55,'CLUB / ELECTRONICA'),
(93339,55,  'CONTEMPORARY FOLK'),
(93344,55,'CHILDREN'),
(94892,65,'EUROPE'),
(4180,10694,'CLASSICAL - SOLO PIANO'),
(94893,94892,'Western & Southern  Europe'),
(94900,94893,'France')

;with CategoryCTE (categoryID, categoryString) as
(
    select categoryID, cast(categoryDesc as nvarchar(max)) as categoryString
    from @Categories 
    where categoryParentID is null

    union all

    select rsCat.categoryID, cast(CategoryCTE.categoryString + N'>>' + rsCat.categoryDesc as nvarchar(max))
    from @Categories rsCat
    inner join CategoryCTE on rsCat.categoryParentID = CategoryCTE.categoryID
)
select categoryString 
from CategoryCTE o
where not exists
(
    --eliminate intermediate strings
    select i.categoryString
    from CategoryCTE i
    where LEN(i.categoryString) != LEN(o.categoryString)
    and CHARINDEX(o.categoryString, i.categoryString) > 0
)

Рабочий пример.

1 голос
/ 30 ноября 2011

Ваши данные выглядят так, что они будут иметь 4 категории глубины, поэтому вы можете попробовать что-то вроде этого:

    SELECT parent.Name, child.Name, subchild.Name, subchild2.Name
    FROM categories parent
    LEFT JOIN categories child ON parent.Id = child.Parent
    LEFT JOIN categories subchild ON child.Id = subchild.Parent
    LEFT JOIN categories subchild2 ON subchild.Id = subchild2.Parent
    WHERE parent.Parent is NULL;

Конечно, вам нужно будет скорректировать их, если в итоге вы получите более 4уровни категорий.Этот метод также в конечном итоге даст результаты NULL для иерархий, которые не распространяются на все 4 уровня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...