2010-07-05 7 views
7

Est-il possible d'élaborer une clause ORDER BY pour garantir les critères suivants pour deux champs (tous les deux de type INT), appelés respectivement child et parent pour cet exemple.Complexe TSQL order by clause

  1. parent références child, mais peut être nulle.
  2. Un parent peut avoir plusieurs enfants; un enfant seul parent.
  3. Un enfant ne peut pas être un parent de lui-même.
  4. Il doit exister au moins un enfant sans parent.
  5. Chaque valeur de child doit apparaître avant qu'elle n'apparaisse dans parent dans le jeu de résultats ordonné.

Je rencontre des difficultés au point 5.

échantillon de données non numérotée:

child parent 
------------ 
1  NULL 
3  5 
4  2 
2  5 
5  NULL 

Il est évident que ni le travail ORDER BY a, b ou ORDER BY b, a. En fait, plus j'y pense, plus je ne suis pas sûr que cela puisse même être fait. Compte tenu des restrictions, les cas évidents tels que:

child parent 
------------ 
1  2 
2  1 

ne sont pas autorisés car il viole les règles 3 et 4 (et évidemment 5).

Alors, est ce que j'essaie d'atteindre possible, et si oui, comment? Plate-forme est SQL Server 2005.

Mise à jour: ordre de tri souhaité pour les données de l'échantillon:

child parent 
------------ 
1  NULL 
5  NULL 
2  5 
3  5 
4  2 

Pour chaque ligne qui définit une valeur non nulle dans la colonne parent, la valeur a déjà été présent Dans la colonne enfant.

+0

Pourriez-vous montrer les données d'échantillon dans l'ordre souhaité, s'il vous plaît? Ce serait une aide. –

+0

Ajouté selon votre demande, Brian. –

Répondre

6

Vous pouvez utiliser un CTE récursive pour trouver la « profondeur » de chaque noeud, et l'ordre par que:

create table node (id int, parent int) 
insert into node values (1, null) 
insert into node values (2, 5) 
insert into node values (3, 5) 
insert into node values (4, 2) 
insert into node values (5, null) 
insert into node values (6, 4); 

with node_cte (id, depth) as (
    select id, 0 from node where parent is null 
    union all 
    select node.id, node_cte.depth + 1 
    from node join node_cte on node.parent = node_cte.id  
) 

select node.* 
from node 
join node_cte on node_cte.id=node.id 
order by node_cte.depth asc 
+1

Ahh, CTE récursifs. Y a-t-il quelque chose qu'ils ne peuvent pas faire? –

1

Vous ne pourrez pas le faire avec une clause 'ORDER BY' car l'exigence 5 spécifie que la commande est sensible à la hiérarchie de données. Dans SQL Server 2005, les données de hiérarchie sont généralement traitées à l'aide de CTE récursifs. peut-être que quelqu'un ici fournira le code approprié pour ce cas.