2009-02-19 11 views
9

Image vous créez un schéma de base de données pour un forum de discussion. Existe-t-il un moyen efficace de sélectionner une liste triée correctement pour un thread donné? Le code que j'ai écrit fonctionne mais ne trie pas comme je le voudrais.CTE SQL récursif et ordre de tri personnalisé

Disons que vous avez ces données:

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

Ainsi, la structure est censé ressembler à ceci:

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

Idéalement, dans le code, nous voulons que le jeu de résultats à apparaître dans la ordre suivant: 1, 2, 3, 5, 4
PROBLÈME: Avec le CTE je l'ai écrit est effectivement retourné comme: 1, 2, 4, 3, 5

Je sais que ce serait facile à grouper/commander en utilisant LINQ mais je suis réticent à le faire en mémoire. Il semble que la meilleure solution à ce stade si ...

est le CTE J'utilise actuellement ici:

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 

Toute aide serait appréciée; Merci!



Je suis novice en SQL et je n'avais jamais entendu parler du type de données hierarchyid auparavant. Après avoir lu à ce sujet de this comment j'ai décidé que je pourrais vouloir l'incorporer dans mon dessin. Je vais expérimenter ce soir et poster plus d'informations si j'ai du succès.


Mise à jour
Résultat obtenu de mes données d'échantillons, en utilisant la suggestion de 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

les dieux sql s'indignent de vos revendications – Shawn

Répondre

0

Hmmmm - Je ne suis pas sûr que votre structure est la mieux adaptée à ce problème. En dehors de ma tête je ne peux pas penser de toute façon à trier les données comme vous le souhaitez dans la requête ci-dessus. Le meilleur que je peux penser est si vous avez une table parente qui relie vos commentaires ensemble (par exemple une table de sujet). Si vous le faites, vous devriez pouvoir simplement joindre vos réponses à cela (vous devrez évidemment inclure la bonne colonne), et ensuite vous pouvez trier par topicID, Level pour obtenir l'ordre de tri que vous recherchez (ou toute autre information sur la table de sujet représente une bonne valeur pour le tri).

0

Envisagez de stocker toute la hiérarchie (avec des déclencheurs pour la mettre à jour si elle change) dans un champ.

Ce champ dans votre exemple aurait: 1,2 1.2.3 1.2.5 1,4

alors il vous suffit de trier sur ce champ, essayez et voyez:

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

oui - c'est ce que l'on appelle le chemin matérialisé –

8

Je suis sûr que vous allez aimer ce. Je trouve récemment à propos de la fonction Dense_Rank(), qui est pour « le classement dans la partition d'un ensemble de résultats », selon MSDN

Vérifiez le code ci-dessous et comment « CommentID » est triée. Dans la mesure où je comprends, vous essayez de partitionner votre ensemble de résultats par ParentCommentID.

Faire attention à la colonne "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

Résultat ci-dessous

+0

Merci pour la suggestion, j'essayais de faire fonctionner denses_rank() au début sans chance. J'ai interrogé votre code sur mes données d'échantillon et cela a fonctionné ... presque. Une rangée était en panne. Je posterai les données ci-dessus. –

1

Vous devez utiliser hierarchyid (SQL2008 uniquement) ou un groupe de chaîne (ou octet) concaténation.

Questions connexes