我该如何订购此查询?

时间:2015-09-22 14:00:05

标签: sql-server

DEMO SQL FIDDLE

我有上面的演示中的查询,但我不知道如何订购此查询,我希望结果是这样的:

 Name
-----
Menu_1
-------
..... Sub_Menu_1
-------
Menu_2
-------
..... Sub_Menu_2
-------
..........Sub_Sub_Menu_2
-------
Menu_3
-------

我该怎么做?感谢

编辑 (来自SQLFiddle演示的信息)

表:

CREATE TABLE Menus 
    (
     IdMenu int  primary key, 
     IdParentMenu varchar(20), 
     Name varchar(30)
    );

数据:

INSERT INTO Menus
(IdMenu, IdParentMenu, Name)
VALUES
('1', '0', 'Menu_1'),
('2', '0', 'Menu_2'),
('3', '0', 'Menu_3'),
('4', '1', 'SubMenu_1'),
('5', '2', 'SubMenu_2'),
('6', '5', 'Sub-SubMenu_2');

我的查询:

WITH MenuCTE (IdMenu, IdParentMenu, ParentMenu, Name, Lvl)
AS
(
    -- Anchor member
    SELECT m.IdMenu, m.IdParentMenu, CAST('' AS varchar) AS ParentMenu, m.Name, 0 AS Lvl
    FROM dbo.Menus AS m
    WHERE CAST(m.IdParentMenu AS INT) = 0
    UNION ALL

    -- Recursive member
    SELECT m.IdMenu, m.IdParentMenu, CAST(mc.Name AS varchar) AS ParentMenu, m.Name, Lvl + 1 AS Lvl
    FROM dbo.Menus AS m
    INNER JOIN MenuCTE AS mc
        ON CAST(m.IdParentMenu AS INT) = mc.IdMenu
)
SELECT IdMenu, IdParentMenu, ParentMenu, REPLICATE('....', Lvl) + Name
FROM MenuCTE
--WHERE Lvl > 0
ORDER BY IdParentMenu
GO

2 个答案:

答案 0 :(得分:3)

添加一个按此字段计算路径和顺序的字段:

WITH MenuCTE (IdMenu, IdParentMenu, ParentMenu, Path, Name, Lvl)
AS
(
    -- Anchor member
    SELECT m.IdMenu, m.IdParentMenu, 
           CAST('' AS varchar) AS ParentMenu, 
           CAST(m.Name AS varchar) AS Path, 
           m.Name AS Name, 
           0 AS Lvl
    FROM dbo.Menus AS m
    WHERE CAST(m.IdParentMenu AS INT) = 0
    UNION ALL

    -- Recursive member
    SELECT m.IdMenu, m.IdParentMenu, 
           CAST(mc.Name AS varchar) AS ParentMenu, 
           CAST(mc.Path + '.'+ m.Name AS varchar) AS Path,
           m.Name, 
           Lvl + 1 AS Lvl
    FROM dbo.Menus AS m
    INNER JOIN MenuCTE AS mc
        ON CAST(m.IdParentMenu AS INT) = mc.IdMenu
)
SELECT IdMenu, IdParentMenu, ParentMenu, 
       REPLICATE('....', Lvl) + Name, Path
FROM MenuCTE
ORDER BY Path

注意:在上面的查询中Path是使用Name字段构建的,因此菜单,子菜单等的排序是根据其名称执行的。 Path值类似于:

Menu_1
Menu_1.SubMenu_1
Menu_2
Menu_2.SubMenu_2
Menu_2.SubMenu_2.Sub-SubMenu_2

如果您想按ID排序,则只需使用Path代替IdMenu构建Name。在这种情况下,Path值将类似于:

1
1.4
2
2.5
2.5.6

Demo here

答案 1 :(得分:1)

这应该是好的。

WITH MenuCTE (IdMenu, IdParentMenu, ParentMenu, Ord, Name, Lvl)
AS
(
    -- Anchor member
    SELECT m.IdMenu, m.IdParentMenu, CAST('' AS varchar) AS ParentMenu, CAST(m.IdMenu AS varchar) as Ord, m.Name, 0 AS Lvl
    FROM dbo.Menus AS m
    WHERE CAST(m.IdParentMenu AS INT) = 0
    UNION ALL

    -- Recursive member
    SELECT m.IdMenu, m.IdParentMenu, CAST(mc.Name AS varchar) AS ParentMenu, cast((mc.Ord + CAST(m.IdMenu AS varchar)) as varchar) as Ord, m.Name, Lvl + 1 AS Lvl
    FROM dbo.Menus AS m
    INNER JOIN MenuCTE AS mc
        ON CAST(m.IdParentMenu AS INT) = mc.IdMenu
)
SELECT ord, IdMenu, IdParentMenu, ParentMenu, REPLICATE('....', Lvl) + Name
FROM MenuCTE
--WHERE Lvl > 0
ORDER BY ord
GO