2017-08-08 1 views
0

J'ai une liste de produits, triés en utilisant un HierarchyId, mais pour certains des éléments, le chemin complet vers le haut de la hiérarchie produit le mauvais résultat. Seulement pour quelques ... Ill démontrer ci-dessous:SQL HierarchyId produisant parfois un mauvais chemin

SELECT 
    ProductId 
    ,Name 
    ,FullName 
    ,Hierarchy 
    ,Hierarchy.ToString() as hierarchyString 
    ,editor.ufn_Product_GetFullName(ProductId) as ufnGetFullName 
    ,Hierarchy.GetLevel() as [level] 
FROM Editor.Product 
WHERE ProductId = 378 
    OR Hierarchy.ToString() like '/16/1/1/%' 
    OR Hierarchy.ToString() = '/16/1/' 
    OR Hierarchy.ToString() = '/16/' 
    OR Hierarchy.ToString() = '/' 
ORDER BY Hierarchy.ToString() 

En utilisant cette requête i obtenir le résultat:

enter image description here La plupart des chemins revient de la procédure sont très bien, la production

'Extérieur> Rendu> Couleur> Blanc'

Cependant quatre d'entre eux produisent les deux derniers termes d'échange ped comme

« Extérieur> Rendu> Blanc> Couleur »

Je ne peux pas pour la vie de moi, de savoir pourquoi les termes sont permutés et pourquoi seulement quelques-uns. La structure de la hiérarchie semble correcte et les niveaux sont tous corrects sur les éléments enfants. J'ai besoin de votre aide ...

Voici la fonction utilisée pour produire le chemin à partir de la hiérarchie du produit, bien que je ne comprenne pas comment cela pourrait être le problème.

ALTER FUNCTION [Editor].[ufn_Product_GetFullName] (@ID INT) 
RETURNS VARCHAR(8000) 
AS BEGIN 
    -- Create and insert names into temp table 
    DECLARE @NamesTable TABLE (Name varchar(8000)); 

    INSERT @NamesTable (Name) 
     SELECT t1.Name 
     FROM ( SELECT ProductId, Hierarchy, Name 
       FROM Product WITH(NOLOCK) 
       WHERE (ProductId = @ID)) AS t2 
      CROSS JOIN Product AS t1 

     WHERE (t1.Hierarchy = t2.Hierarchy) 
     OR (t1.Hierarchy <> '/') 
     AND (t2.Hierarchy.IsDescendantOf(t1.Hierarchy) = 1) 

     ORDER BY t1.Hierarchy; 

    -- Define name string 
    DECLARE @Name VARCHAR(8000); 

    -- Coalesce names from temp table into one long string 
    SELECT @Name = COALESCE(@Name + ' > ', '') + Name 
    FROM @NamesTable 

    -- Return full string 
    RETURN @Name 
END 
+0

Est-ce vraiment un code MySQL? – jarlh

Répondre

1

Sans ORDER BY clause vous ne pouvez pas être sûr de l'ordre des lignes. Ajouter la colonne Level au tableau @NamesTable. Ajoutez la clause ORDER BY à SELECT où vous concédez des chaînes. Cela devrait aider.

ALTER FUNCTION [Editor].[ufn_Product_GetFullName] (@ID INT) 
RETURNS VARCHAR(8000) 
AS BEGIN 
    -- Create and insert names into temp table 
    DECLARE @NamesTable TABLE (Name varchar(8000), Level int); 

    INSERT @NamesTable (Name, Level) 
     SELECT t1.Name, t1.Hierarchy.getLevel() 
     FROM ( SELECT ProductId, Hierarchy, Name 
       FROM Product WITH(NOLOCK) 
       WHERE (ProductId = @ID)) AS t2 
      CROSS JOIN Product AS t1 

     WHERE (t1.Hierarchy = t2.Hierarchy) 
     OR (t1.Hierarchy <> '/') 
     AND (t2.Hierarchy.IsDescendantOf(t1.Hierarchy) = 1) 

     ORDER BY t1.Hierarchy; 

    -- Define name string 
    DECLARE @Name VARCHAR(8000); 

    -- Coalesce names from temp table into one long string 
    SELECT @Name = COALESCE(@Name + ' > ', '') + Name 
    FROM @NamesTable 
    ORDER BY Level 

    -- Return full string 
    RETURN @Name 
END 
+1

Pour le faire, j'ai dû ajouter Level à la ligne INSERT @NamesTable (Name) et changer votre t1.level en t1.Hierarchy.getLevel() mais sinon ça a fonctionné parfaitement merci :) – Xynos

+0

Désolé! J'ai totalement oublié ça. Je vais mettre à jour ma réponse. – Rokuto