2008-10-24 3 views
11

À l'époque où je travaillais dans un magasin Oracle, je prenais le CONNECT_BY pour acquis. Maintenant, je suis coincé avec SQL Server 2005 et j'ai quelques mauvaises hiérarchies d'objets. Plus précisément, nous avons une table d'auto-référence où tous les enregistrements enfants ont une colonne avec l'ID de leur parent. Actuellement, nous avons une vue qui mappe les enfants aux niveaux de la hiérarchie et une mauvaise requête qui fait le gros du travail pour connecter les parents avec leurs enfants. Bien que cette méthode fonctionne, elle est loin d'être élégante et puante. Je suis juste curieux de savoir comment d'autres personnes récupèrent des données hiérarchiques à partir de SQL Server 2005.Requêtes hiérarchiques dans SQL Server 2005

Répondre

1

Dans SQL Server 2005, vous pouvez utiliser Common Table Expressions (CTE) pour cela.

+0

la force récursif est un() vous. har har har. –

+0

Pourriez-vous montrer un exemple? –

25

Ceci crée votre table hiérarchique typique et utilise un CTE pour sélectionner la structure de la hiérarchie et créer un chemin pour chaque élément.

CREATE TABLE tblHierarchy (ID int, ParentID int NULL, Name varchar(128)); 

INSERT INTO tblHierarchy VALUES (1, NULL, '1'); 
INSERT INTO tblHierarchy VALUES (2, NULL, '2'); 
INSERT INTO tblHierarchy VALUES (3, NULL, '3'); 
INSERT INTO tblHierarchy VALUES (4, 1, '1.1'); 
INSERT INTO tblHierarchy VALUES (5, 1, '1.2'); 
INSERT INTO tblHierarchy VALUES (6, 4, '1.1.1'); 

WITH Parent AS 
(
    SELECT 
     ID, 
     ParentID, 
     Name AS Path 
    FROM 
     tblHierarchy 
    WHERE 
     ParentID IS NULL 

    UNION ALL 

    SELECT 
     TH.ID, 
     TH.ParentID, 
     CONVERT(varchar(128), Parent.Path + '/' + TH.Name) AS Path 
    FROM 
     tblHierarchy TH 
    INNER JOIN 
     Parent 
    ON 
     Parent.ID = TH.ParentID 
) 
SELECT * FROM Parent 

SORTIE:

ID ParentID Path 
1 NULL  1 
2 NULL  2 
3 NULL  3 
4 1  1/1.1 
5 1  1/1.2 
6 4  1/1.1/1.1.1 
3

Juste Pour votre information. SQL Server 2008 prend en charge un nouveau type de données Hierarchy ID.

2

Lire ceci:

http://www.sitepoint.com/article/hierarchical-data-database/2/

Il devrait vous donner quelques idées ...

+0

Oui, les ensembles imbriqués sont définitivement la solution idéale pour les hiérarchies illimitées dans un SGBDR. La description de Sitepoint le rend un peu plus compliqué qu'il ne l'est en réalité, et les implémentations peuvent être simplifiées, par exemple. en ayant un «ordre de classement» et un «rang de voisin» au lieu de «gauche» et «droit». – bobince

3

Ayant utilisé à la fois, j'ai trouvé CONNECT BY est un peu plus souple et plus facile à utiliser que CTE. La question n'est pas différente de celle à laquelle j'ai répondu il y a quelques semaines. Voir Here pour une brève comparaison de CONNECT BY et CTE et Here pour un exemple d'une requête utilisant CTE.

+0

Tough luck que CONNECT BY n'existe pas dans MSSQL. –

0

Pour parcourir la profondeur de la hiérarchie d'abord, puis le niveau de frères et soeurs, CTE peut être utilisé:

declare @tempTable TABLE 
(
    ORGUID int, 
    ORGNAME nvarchar(100), 
    PARENTORGUID int, 
    ORGPATH nvarchar(max) 
) 

;WITH RECORG(ORGuid, ORGNAME, PARENTORGUID, ORGPATH) 
as 
(
    select 
     org.UID, 
     org.Name, 
     org.ParentOrganizationUID, 
     dbo.fGetOrganizationBreadcrumbs(org.UID) 
    from Organization org 
    where org.UID =1 

    union all 

    select 
     orgRec.UID, 
     orgRec.Name, 
     orgRec.ParentOrganizationUID, 
     dbo.fGetOrganizationBreadcrumbs(orgRec.UID) 
    from Organization orgRec 
    inner join RECORG recOrg on orgRec.ParentOrganizationUID = recOrg.ORGuid 

) 
insert into @tempTable(ORGUID, ORGNAME, PARENTORGUID,ORGPATH) 

select ORGUID, ORGNAME, PARENTORGUID,ORGPATH 
from RECORG rec 

select * 
from @tempTable where ORGUID in(select MIN(tt.ORGUID) 
           from @tempTable tt 
           group by tt.PARENTORGUID)