递归SQL CTE和自定义排序顺序

时间:2009-02-19 16:20:15

标签: sql linq tsql recursion common-table-expression

您正在为线程化讨论板创建数据库架构的映像。有没有一种有效的方法为给定的线程选择正确排序的列表?我写的代码有效,但不按照我想要的方式排序。

假设您有这些数据:

ID   |  ParentID
-----------------
1    |   null
2    |   1
3    |   2
4    |   1
5    |   3

所以结构应该是这样的:

1
|- 2
|  |- 3
|  |  |- 5
|- 4

理想情况下,在代码中,我们希望结果集按以下顺序显示: 1,2,3,5,4
问题:我写的CTE实际上是以 1,2,4,3,5

的形式返回的

我知道使用LINQ很容易分组/订购,但我不愿意在内存中这样做。这似乎是目前最好的解决方案......

以下是我目前正在使用的CTE:

with Replies as (   
    select c.CommentID, c.ParentCommentID 1 as Level
        from Comment c
        where ParentCommentID is null and CommentID = @ParentCommentID

    union all

    select c.CommentID, c.ParentCommentID, r.Level + 1 as Level
       from Comment c
       inner join Replies r on c.ParentCommentID = r.CommentID
)

select * from Replies

任何帮助将不胜感激;谢谢!



我是SQL的新手,之前没有听说过hierarchyid数据类型。在从this comment阅读之后,我决定将其纳入我的设计中。如果我成功的话,今晚我会试验这个并发布更多信息。

<小时/> 更新
使用dance2die的建议从我的样本数据返回结果:

ID  |  ParentID  | Level  | DenseRank
-------------------------------------
15     NULL          1         1
20     15            2         1
21     20            3         1
17     22            3         1
22     15            2         2
31     15            2         3
32     15            2         4
33     15            2         5
34     15            2         6
35     15            2         7
36     15            2         8

4 个答案:

答案 0 :(得分:8)

我相信你会这个。 我最近发现了Dense_Rank()函数,它是根据MSDN

用于“在结果集的分区内排名”的函数

查看下面的代码以及“CommentID”的排序方式。

据我了解,您正在尝试按ParentCommentID对结果集进行分区。

注意“密集”栏目。

with Replies (CommentID, ParentCommentID, Level) as 
(
        select  c.CommentID, c.ParentCommentID, 1 as Level
        from    Comment c
        where   ParentCommentID is null and CommentID = 1

        union all

        select  c.CommentID, c.ParentCommentID, r.Level + 1 as Level
        from    Comment c
                inner join Replies r on c.ParentCommentID = r.CommentID
)
select  *,
        denserank = dense_rank() over (partition by ParentCommentID order by CommentID)
from    Replies
order by denserank

alt text

以下结果

答案 1 :(得分:1)

您必须使用hierarchyid(仅限sql2008)或一堆字符串(或字节)连接。

答案 2 :(得分:0)

嗯 - 我不确定你的结构是否最适合这个问题。无论如何,我无法想到在上述查询中根据需要对数据进行排序。

我能想到的最好的方法是,如果你有一个将你的评论联系起来的父表(例如主题表)。如果你这样做,你应该能够简单地将你的回复加入到那里(显然你需要包含正确的列),然后你可以按主题ID,级别进行排序,以获得你所追求的排序顺序(或其他任何信息)主题表代表了一个很好的排序值。

答案 3 :(得分:0)

考虑在一个字段中存储整个层次结构(如果它发生变化,使用触发器更新它)。

您示例中的此字段包含: 1 1.2 1.2.3 1.2.5 1.4

然后你只需对该字段进行排序,试试看,然后看:

create table #temp (test varchar (10))
insert into #temp (test)
select '1'
union select '1.2'
union select '1.2.3'
union select '1.2.5'
union select '1.4'
select * from #temp order by test asc