2009-02-19 25 views
9

immagine che si sta creando uno schema DB per un forum di discussione filettata. C'è un modo efficace per selezionare una lista ordinata correttamente per un determinato thread? Il codice che ho scritto funziona ma non ordina come vorrei.ricorsiva SQL CTE e Ordinamento personalizzato per l'ordine

Diciamo che avete questi dati:

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

Quindi la struttura dovrebbe assomigliare a questo:

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

Idealmente, nel codice, vogliamo che il set di risultati da visualizzare nel seguente ordine: 1, 2, 3, 5, 4
PROBLEMA: Con CTE ho scritta è effettivamente restituito come: 1, 2, 4, 3, 5

So che sarebbe facile raggruppare/ordinare usando LINQ ma sono riluttante a farlo in memoria. Sembra che la soluzione a questo punto però meglio ...

Ecco l'CTE Attualmente sto usando:

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 

Qualsiasi aiuto sarebbe apprezzato; Grazie!



Sono nuovo di SQL e non avevano sentito parlare tipo di dati hierarchyid prima. Dopo aver letto su di esso da this comment ho deciso che potrei voler incorporare questo nel mio progetto. Sperimenterò con questo stasera e pubblicherò maggiori informazioni se avrò successo.


Aggiornamento
risultato restituito dai miei dati di esempio, utilizzando il suggerimento di 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

gli dei sql crescono indignati dalle tue affermazioni – Shawn

risposta

0

Hmmmm - Io non sono sicuro se la struttura è il più adatto per questo problema. In cima alla mia testa non riesco a pensare comunque a ordinare i dati come lo desideri all'interno della query precedente.

Il meglio che posso pensare è se si dispone di una tabella principale che lega insieme i tuoi commenti (ad es. Un tavolo argomento). Se lo fai si dovrebbe essere in grado di unirsi semplicemente le vostre risposte su quella (è necessario includere la colonna corretta, ovviamente), e quindi è possibile ordinare per la TopicId, livello per ottenere l'ordinamento si sta dopo (o qualsiasi altra informazioni la tabella degli argomenti rappresenta un buon valore per l'ordinamento).

0

consideri memorizzare l'intera gerarchia (con i trigger di aggiornarlo se cambia) in un campo.

Questo campo nel tuo esempio avrebbe: 1,2 1.2.3 1.2.5 1,4

Poi basta per ordinare su quel campo, provate questo e vedere:

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

sì - questo si chiama percorso materializzato –

8

sono sicuro che si vuole amore questo. recente ho scoprire su Dense_Rank() funzione, che è per "classifica all'interno della partizione di un set di risultati", secondo MSDN

Partenza il codice qui sotto e come "CommentID" è ordinato.

Per quanto ho capito, si sta tentando di partizionare il set di risultati da ParentCommentID.

Prestare attenzione alla colonna "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

Risultato sotto

+0

Grazie per il suggerimento, stavo cercando di far funzionare dense_rank() all'inizio senza fortuna. Ho interrogato il tuo codice sui miei dati di esempio e ha funzionato ... quasi. Una fila era fuori uso. Pubblicherò i dati sopra. –

1

Devi usare hierarchyid (solo SQL2008) o di un gruppo di stringa (byte o) concatenazione.