SQL рекурсивная сортировка меню - PullRequest
1 голос
/ 19 ноября 2009

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

CREATE TABLE [dbo].[Categories](
    [ID] [int] IDENTITY(1,1) NOT NULL,
[Title] [varchar](256) NOT NULL,
[ParentID] [int] NOT NULL,
CONSTRAINT [PK_Categories] PRIMARY KEY CLUSTERED 
(
[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('All', 0)
INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('Banking', 8)
INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('USAA Checking', 2)
INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('USAA Mastercard', 2)
INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('Medical', 8)
INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('Jobs', 8)
INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('Archive', 1)
INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('Active', 1)
INSERT INTO [MDS].[dbo].[Categories]([Title],[ParentID]) VALUES ('BoA Amex', 2)

Все хорошо, кроме выбора всего дерева. Вот мой запрос, я удалил свой ORDER BY, потому что он не работает:

WITH CategoryTree (ID, Title, Level, ParentID) AS
(
   SELECT  r.ID, r.Title, 0 Level, r.ParentID
   FROM Categories r
   WHERE r.ParentID = 0

   UNION ALL

   SELECT c.ID, c.Title, p.Level + 1 AS Level, c.ParentID
   FROM Categories c
   INNER JOIN CategoryTree p
      ON p.ID = c.ParentID
)

SELECT  ID,
    REPLICATE('-----', Level) + Title AS Title,
    ParentID
FROM CategoryTree

Результаты:

ID  Title                        ParentID
1   All                              0
7   -----Archive                     1
8   -----Active                      1
2   ----------Banking                8
5   ----------Medical                8
6   ----------Jobs                   8
3   ---------------USAA Checking     2
4   ---------------USAA Mastercard   2
9   ---------------BoA Amex          2

Результат, который я хочу получить, таков:

ID  Title                            ParentID
1   All                               0
8   -----Active                      1
2   ----------Banking                8
9   ---------------BoA Amex          2
3   ---------------USAA Checking     2
4   ---------------USAA Mastercard   2
6   ----------Jobs                   8
5   ----------Medical                8
7   -----Archive                     1

Что меня убивает, так это то, что раньше я прекрасно работал, но потом я забыл сделать резервную копию БД и потерял ее при обновлении сервера.

Я посмотрел на тип HierarchyID в 2008 году, но это просто большая боль в заднице, если вы заботитесь о порядке детей на том же уровне.

1 Ответ

5 голосов
/ 19 ноября 2009

Хорошо, понял :) - Это похоже на работу здесь.

DECLARE @Categories TABLE (
 ID int PRIMARY KEY
,Title varchar(256)
,ParentID int
)

INSERT INTO @Categories
VALUES
 (1, 'All', 0)
,(2,'Banking', 8)
,(3,'USAA Checking', 2)
,(4,'USAA Mastercard', 2)
,(5,'Medical', 8)
,(6,'Jobs', 8)
,(7,'Archive', 1)
,(8,'Active', 1)
,(9,'BoA Amex', 2)


;
WITH  CategoryTree
        AS (SELECT  r.ID, r.Title, 0 Level, r.ParentID,
                    CAST(r.Title AS VARCHAR(1000)) AS "Path"
            FROM    @Categories r
            WHERE   r.ParentID = 0
            UNION ALL
            SELECT  c.ID, c.Title, p.Level + 1 AS Level, c.ParentID,
                    CAST((p.path + '/' + c.Title) AS VARCHAR(1000)) AS "Path"
            FROM    @Categories c
                    INNER JOIN CategoryTree p
                      ON p.ID = c.ParentID
           )
  SELECT  ID, REPLICATE('-----', Level) + Title AS Title, [Path]
  FROM    CategoryTree
  ORDER BY [Path]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...