SQL - 按多个条件排序

时间:2009-07-06 08:40:10

标签: sql sql-server-2005 tsql

我有一张类别表。每个类别可以是根级别类别(父级为NULL),也可以是父级别是根级别类别。嵌套的级别不能超过一个。

我有以下表结构:

Categories Table Structure http://img16.imageshack.us/img16/8569/categoriesi.png

有什么方法可以使用产生以下输出的查询:

Free Stuff
Hardware
Movies
CatA
CatB
CatC
Software
Apples
CatD
CatE

所以结果按顶级类别排序,然后在每个顶级类别之后,列出该类别的子类别?

它不是按父或姓名排序,而是两者的组合。我正在使用SQL Server。

6 个答案:

答案 0 :(得分:4)

在我看来,您希望扁平化并对您的层次结构进行排序,获得此排序的最便宜方式是在表中存储具有完整路径的其他列。

例如:

Name            | Full Path
Free Stuff      | Free Stuff 
aa2             | Free Stuff - aa2            

存储完整路径后,您可以订购。

如果你只有一个深度,你可以使用一个子查询(及其上的顺序)自动生成一个字符串,但是这个解决方案在深入时不会那么容易。

另一种选择是将其全部移动到临时表并根据需要计算其中的完整路径。但它相当昂贵。

答案 1 :(得分:2)

您可以让表格看自己,按父名称排序,然后按子名称排序。

select   categories.Name AS DisplayName
from     categories LEFT OUTER JOIN
         categories AS parentTable ON categories.Parent = parentTable.ID
order by parentTable.Name, DisplayName

答案 2 :(得分:1)

不完全确定您的问题,但听起来PARTITION BY可能对您有用。关于PARTITION BY here的介绍性文章很好。

答案 3 :(得分:1)

好的,我们走了:

with foo as
(
select 1 as id, null as parent, 'CatA' as cat from dual
union select 2, null, 'CatB' from dual
union select 3, null, 'CatC' from dual
union select 4, 1, 'SubCatA_1' from dual
union select 5, 1, 'SubCatA_2' from dual
union select 6, 2, 'SubCatB_1' from dual
union select 7, 2, 'SubCatB_2' from dual
)
select child.cat
from foo parent right outer join foo child on parent.id = child.parent
order by case when parent.id is not null then parent.cat else child.cat end,
         case when parent.id is not null then 1 else 0 end

结果:

CatA
SubCatA_1
SubCatA_2
CatB
SubCatB_1
SubCatB_2
CatC

编辑 - 解决方案的变化激发了van的订单!这样简单得多。

答案 4 :(得分:1)

这里有一个使用递归公用表表达式的完整工作示例。

DECLARE @categories TABLE
(
    ID INT NOT NULL,
    [Name] VARCHAR(50),
    Parent INT NULL
);

INSERT INTO @categories VALUES (4,  'Free Stuff', NULL);
INSERT INTO @categories VALUES (1,  'Hardware', NULL);
INSERT INTO @categories VALUES (3,  'Movies', NULL);
INSERT INTO @categories VALUES (2,  'Software', NULL);
INSERT INTO @categories VALUES (10, 'a', 0);
INSERT INTO @categories VALUES (12, 'apples', 2);
INSERT INTO @categories VALUES (8,  'catD', 2);
INSERT INTO @categories VALUES (9,  'catE', 2);
INSERT INTO @categories VALUES (5,  'catA', 3);
INSERT INTO @categories VALUES (6,  'catB', 3);
INSERT INTO @categories VALUES (7,  'catC', 3);
INSERT INTO @categories VALUES (11, 'aa2', 4);

WITH categories(ID, Name, Parent, HierarchicalName)
AS
(
    SELECT
        c.ID
        , c.[Name]
        , c.Parent
        , CAST(c.[Name] AS VARCHAR(200)) AS HierarchicalName
    FROM @categories c
    WHERE c.Parent IS NULL

    UNION ALL

    SELECT
        c.ID
        , c.[Name]
        , c.Parent
        , CAST(pc.HierarchicalName + c.[Name] AS VARCHAR(200))
    FROM @categories c
    JOIN categories pc ON c.Parent = pc.ID
)
SELECT c.*
FROM categories c
ORDER BY c.HierarchicalName

答案 5 :(得分:1)

SELECT
  ID,
  Name,
  Parent,
  RIGHT(
    '000000000000000' + 
    CASE WHEN Parent IS NULL 
    THEN CONVERT(VARCHAR, Id) 
    ELSE CONVERT(VARCHAR, Parent) 
    END, 15
  )
  + '_' + CASE WHEN Parent IS NULL THEN '0' ELSE '1' END
  + '_' + Name
FROM
  categories
ORDER BY
  4

长填充是为了解释SQL Server的INT数据类型从2,147,483,648到2,147,483,647的事实。

您可以直接ORDER BY表达式,无需使用ORDER BY 4。它只是为了展示它的分类。

值得注意的是,这个表达式不能使用任何索引。这意味着对大表进行排序会很慢。