代码之家  ›  专栏  ›  技术社区  ›  Echilon Mafarnakus

SQL-按多个条件排序

  •  1
  • Echilon Mafarnakus  · 技术社区  · 16 年前

    我有以下表格结构:

    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 回复  |  直到 16 年前
        1
  •  1
  •   Cyril Gandon niktrs    16 年前

    在我看来,您似乎希望对层次结构进行扁平化和排序,获得这种排序的最便宜的方法是在表中存储一个具有完整路径的额外列。

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

    一旦你存储了完整的路径,你就可以在上面订购。

    如果你只有一个深度,你可以通过一个子查询(及其顺序)自动生成一个字符串,但当它变深时,这个解决方案就不那么容易工作了。

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

        2
  •  4
  •   Sam Saffron James Allen    16 年前

    您可以使表按父名称和子名称进行排序。

    select   categories.Name AS DisplayName
    from     categories LEFT OUTER JOIN
             categories AS parentTable ON categories.Parent = parentTable.ID
    order by parentTable.Name, DisplayName
    
        3
  •  2
  •   Iain Hoult    16 年前

    好的,我们开始吧:

    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
    

        4
  •  1
  •   super9    16 年前

    不完全确定你的问题,但听起来PARTITION BY可能对你有用。PARTITION BY上有一篇很好的介绍性文章 here .

        5
  •  1
  •   Ronald Wildenberg    16 年前

    在这里,您有一个使用重铺公共表表达式的完整工作示例。

    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
    
        6
  •  1
  •   Tomalak    16 年前
    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
    

    ORDER BY ORDER BY 4 。这只是为了显示它正在排序什么。

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