Je dois obtenir une hiérarchie ordonnée d'un arbre, d'une manière spécifique. La table en question ressemble un peu à ceci (tous les champs d'ID sont des identifiants uniques, j'ai simplifié les données à titre d'exemple):
EstimateItemID EstimateID ParentEstimateItemID ItemType -------------- ---------- ----------------- --- -------- 1 Un produit NULL 2 Un 1 produit 3 Un service 2 4 Un produit NULL 5 A 4 produit 6 A 5 service 7 A 1 service 8 A 4 produit
Vue graphique de l'arborescence (* indique 'service'):
A ___/\ ___ /\ 1 4 /\/\ 2 7 * 5 8 // 3* 6 *
En utilisant cette requête, je peux obtenir la hiérarchie (supposons simplement que "A" est un identifiant unique, je sais que ce n’est pas dans la vie réelle):
DECLARE @EstimateID uniqueidentifier
SELECT @EstimateID = 'A'
;WITH temp as(
SELECT * FROM EstimateItem
WHERE EstimateID = @EstimateID
UNION ALL
SELECT ei.* FROM EstimateItem ei
INNER JOIN temp x ON ei.ParentEstimateItemID = x.EstimateItemID
)
SELECT * FROM temp
Cela me donne les enfants de EstimateID 'A', mais dans l'ordre dans lequel il apparaît dans le tableau. c'est à dire:
EstimateItemID -------------- 1 2 3 4 5 6 7 8
Malheureusement, il me faut une hiérarchie ordonnée avec un ensemble de résultats qui respecte les contraintes suivantes:
1. chaque branche doit être groupée 2. les enregistrements avec ItemType 'product' et parent sont le nœud supérieur 3. enregistrements avec ItemType 'product' et parent non NULL groupés après le nœud supérieur 4. les enregistrements avec ItemType 'service' sont le noeud inférieur d'une branche
Ainsi, l'ordre dans lequel j'ai besoin des résultats, dans cet exemple, est:
EstimateItemID -------------- 1 2 3 7 4 5 8 6
Que dois-je ajouter à ma requête pour y parvenir?
Essaye ça:
;WITH items AS (
SELECT EstimateItemID, ItemType
, 0 AS Level
, CAST(EstimateItemID AS VARCHAR(255)) AS Path
FROM EstimateItem
WHERE ParentEstimateItemID IS NULL AND EstimateID = @EstimateID
UNION ALL
SELECT i.EstimateItemID, i.ItemType
, Level + 1
, CAST(Path + '.' + CAST(i.EstimateItemID AS VARCHAR(255)) AS VARCHAR(255))
FROM EstimateItem i
INNER JOIN items itms ON itms.EstimateItemID = i.ParentEstimateItemID
)
SELECT * FROM items ORDER BY Path
Avec Path
- lignes a triées par noeuds parents
Si vous voulez trier les enfants de ItemType
pour chaque niveau, vous pouvez jouer avec Level
et SUBSTRING
de Path
column ....
Ici SQLFiddle avec un échantillon de données
C'est un ajout à la grande idée de Fabio vue d'en haut. Comme je l'ai dit dans ma réponse à son message d'origine. J'ai republié son idée en utilisant des données, un nom de table et des champs plus communs pour que d'autres puissent le suivre plus facilement.
Merci Fabio! Grand nom en passant.
D'abord quelques données avec lesquelles travailler:
CREATE TABLE tblLocations (ID INT IDENTITY(1,1), Code VARCHAR(1), ParentID INT, Name VARCHAR(20));
INSERT INTO tblLocations (Code, ParentID, Name) VALUES
('A', NULL, 'West'),
('A', 1, 'WA'),
('A', 2, 'Seattle'),
('A', NULL, 'East'),
('A', 4, 'NY'),
('A', 5, 'New York'),
('A', 1, 'NV'),
('A', 7, 'Las Vegas'),
('A', 2, 'Vancouver'),
('A', 4, 'FL'),
('A', 5, 'Buffalo'),
('A', 1, 'CA'),
('A', 10, 'Miami'),
('A', 12, 'Los Angeles'),
('A', 7, 'Reno'),
('A', 12, 'San Francisco'),
('A', 10, 'Orlando'),
('A', 12, 'Sacramento');
Maintenant la requête récursive:
-- Note: The 'Code' field isn't used, but you could add it to display more info.
;WITH MyCTE AS (
SELECT ID, Name, 0 AS TreeLevel, CAST(ID AS VARCHAR(255)) AS TreePath
FROM tblLocations T1
WHERE ParentID IS NULL
UNION ALL
SELECT T2.ID, T2.Name, TreeLevel + 1, CAST(TreePath + '.' + CAST(T2.ID AS VARCHAR(255)) AS VARCHAR(255)) AS TreePath
FROM tblLocations T2
INNER JOIN MyCTE itms ON itms.ID = T2.ParentID
)
-- Note: The 'replicate' function is not needed. Added it to give a visual of the results.
SELECT ID, Replicate('.', TreeLevel * 4)+Name 'Name', TreeLevel, TreePath
FROM MyCTE
ORDER BY TreePath;
Je crois que vous devez ajouter ce qui suit aux résultats de votre CTE ...
Si ceux-ci existent dans la sortie, je pense que vous devriez pouvoir utiliser la sortie de votre requête comme un autre CTE ou comme clause FROM dans une requête. Ordre par BranchID, ItemTypeID, Parent.