2009-02-19 79 views
9

您正在为线程讨论板创建数据库模式的图像。有没有一种有效的方法来为给定的线程选择正确排序的列表?我编写的代码虽然不符合我喜欢的方式。递归SQL CTE和自定义排序顺序

比方说,你有这样的数据:

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
+0

sql gods从你的声明中发出愤慨 – Shawn 2009-02-19 16:44:38

回答

0

Hmmmm - 我不知道,如果你的结构是最适合这个问题。关于我的头顶,我无法想象在上述查询中按照您的需要对数据进行排序。

我能想到的最好方法是如果你有一个将你的评论联系在一起的父表(例如,一个主题表)。如果你确实应该能够简单地将你的回复加入到你的回复中(显然你需要包含正确的列),然后你可以通过topicID,Level来排序,以获得你之后的排序顺序(或者任何其他信息主题表格代表了排序的好价值)。

0

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

此字段在您的例子有: 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 
+0

是的 - 这被称为物化路径 – 2009-07-06 23:48:17

8

我相信你会这个。 我最近了解Dense_Rank()功能,这是根据MSDN

看看下面的代码,以及如何“结果集的分区内的排名”,“CommentID”进行排序。

据我所知,您正试图按ParentCommentID对您的结果集进行分区。

注意“denserank”栏。

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

结果如下

+0

感谢您的建议,我试图让dense_rank()在第一次运行没有运气。我在我的示例数据上查询了您的代码,它几乎可以工作。一行失灵。我会发布上面的数据。 – 2009-02-20 19:36:06

1

你必须使用HIERARCHYID(仅SQL2008)或一串字符串(或字节)级联。