动态订单使用父值和混合列类型

时间:2013-08-16 11:26:33

标签: sql sql-server tsql sql-order-by

我有一个名为Report的表格,Report中的列如下:

Id(char)     
Name(char)     
ParentId(char)     
Sequence(int)     
SortBy(char)

该表有一些层次结构。每行的ParentId是另一行Id(顶层的ParentId为NULL)。 SortBy字段为"Name""Sequence"

现在我想要一个SELECT * FROM Report。我希望获得的结果是ParentId分组,但在每个组中,它按SortBy排序,其中SortBy的值在行ID =此组'中s ParentId。

更具体地说,如果某个群组的ParentId"animal",那么该ID为SortBy的行的"animal""Name",我希望此群组是按"Name"排序。

有人可以帮忙吗?非常感谢你的时间!

3 个答案:

答案 0 :(得分:2)

select r.*
from Report r
    left join Report p on p.ID = r.ParentID
order by r.ParentID,
    case p.SortBy
        when 'Sequence' then right('0000000000' + cast(r.Sequence as varchar(10)), 10)
        else r.Name
    end

答案 1 :(得分:2)

您可以在订单中使用CASE按父项动态排序。您的案例唯一棘手的问题是您可以排序的列是不同的数据类型。在这种情况下,您必须将它们转换为通用数据类型。

查询

查询很简单。左连接到父级并使用父级确定案例中的第二个排序参数。第一个排序参数是parentId - 它将孩子们组合在一起。

有两种方法可以处理Sequence。您可以将其转换为varachar并使用pad,或添加第三个sort参数。执行计划没有变化,但如果Sequence索引

,我希望按类别按列分隔订单会更好
SELECT Child.*
FROM #Report [Child]
LEFT JOIN #Report [Parent] ON Parent.Id = Child.ParentId
ORDER BY 
    Child.ParentId,
    CASE Parent.SortBy WHEN 'Name' THEN Child.Name END,
    Sequence -- sort by sequence if no column is matched

替代ORDER BY

ORDER BY 
    Child.ParentId,
    CASE Parent.SortBy
        WHEN 'Name' THEN Child.Name
        ELSE RIGHT('0000000000' + CAST(Child.Sequence AS VARCHAR), 10)
    END

设置代码

IF EXISTS (SELECT * FROM tempdb.sys.objects WHERE NAME LIKE '#Report%') 
    DROP TABLE #Report;

CREATE TABLE #Report
(
    Id CHAR(20),     
    Name CHAR(20),
    ParentId CHAR(20),
    Sequence INT,
    SortBy CHAR(20)
);

INSERT INTO #Report VALUES
('a', 'zName', 'f', 2, ''),
('b', 'bName', 'f', 3, ''),
('c', 'cName', 'g', 7, ''),
('d', 'dName', 'g', 5, ''),
('e', 'eName', 'g', 6, ''),
('f', 'fName', '', 9, 'Name'),
('g', 'gName', '', 8, 'Sequence');

输出

Id  Name    ParentId    Sequence    SortBy
f   fName               9           Name                
g   gName               8           Sequence            
b   bName    f          3                       
a   zName    f          2                       
d   dName    g          5                       
e   eName    g          6                       
c   cName    g          17              

答案 2 :(得分:1)

这是使用RANK OVERUNION

的替代选项
SELECT Child.*, RANK() OVER (PARTITION BY Child.ParentID ORDER BY Child.Sequence) AS Ranked
FROM Report Child
LEFT JOIN Report Parent  ON Parent.ID = Child.ParentID
WHERE Parent.SortBy = 'Sequence'
ORDER BY Child.ParentID, Ranked
SELECT Child.*, RANK() OVER (PARTITION BY Child.ParentID ORDER BY Child.Name) AS Ranked
FROM Report Child
LEFT JOIN Report Parent  ON Parent.ID = Child.ParentID
WHERE Parent.SortBy = 'Name'
ORDER BY Child.ParentID, Ranked