1

我有一个名为 的表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 = 此组的 ParentId 行中。

更具体地说,如果一个组ParentId"animal",则SortById 所在的行"animal""Name",我希望这个组按 排序"Name"

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

4

3 回答 3

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
于 2013-08-16T12:10:43.267 回答
2

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

询问

查询很简单。Left join 到 parent 并使用 parent 来确定 case 中的第二个排序参数。第一个排序参数是parentId-- ,它将子项分组在一起。

有两种处理方式Sequence。您可以将其转换为 varachar 并使用 pad,或者添加第三个排序参数。执行计划没有变化,但是如果列有索引,我希望按类型按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              
于 2013-08-16T12:18:56.103 回答
1

这是使用RANK OVER和的替代选项UNION

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
于 2013-08-16T12:40:01.660 回答