IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Organisation d'une table d'arborescence [2014]


Sujet :

Développement SQL Server

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2017
    Messages : 11
    Points : 11
    Points
    11
    Par défaut Organisation d'une table d'arborescence
    Bonjour j'ai crée une requête récursive qui me donne une arborescence de pièce avec leur composants
    Je donne un exemple se sera plus parlant.
    Tout d'abord ma requête récursive

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    WITH [Ttemp] (Part_No, Parent_No, Versioning, [level]) AS 
    	(
    	--On sélectionne la pièces incriminer
    	SELECT Comp.Component_Part_No, Comp.Parent_Part_No, Comp.Component_Issue, 0 AS [level]
    		FROM PARADEMODW.dbo.Components AS Comp
    		WHERE LTRIM(RTRIM(Comp.Component_Part_No)) = @PartVar AND RTRIM(LTRIM(Comp.Component_Issue)) LIKE '%'+@IssueVar+'%'
    		UNION ALL
    	--On sélectionne ensuite les pièces lié à la pièces incriminer
    	SELECT Comp.Component_Part_No, Comp.Parent_Part_No, Comp.Parent_Issue, [level] + 1
    		FROM PARADEMODW.dbo.Components AS Comp
    		INNER JOIN Ttemp AS temp
    		ON LTRIM(RTRIM(Comp.Parent_Part_No)) = LTRIM(RTRIM(Temp.Part_No))
    		WHERE RTRIM(LTRIM(Comp.Parent_Issue)) = LTRIM(RTRIM(Temp.Versioning))
    	)
    --On affiche ensuite toutes les pièces sans les doublons
    SELECT DISTINCT * 
    	FROM Ttemp
    	ORDER BY [level] ASC
    Ce qui pose soucis n'est probablement pas la récursivité (mais je me trompe peut être) c'est le ORDER BY où je ne sais pas vraiment comment je dois ranger mon tableau. On va passer à l'exemple ce sera plus clair.
    Je cherche toutes les informations liées à la pièce X qui permet de fabriquer la pièce W. La pièce X est composée de la pièce XX et XY. La pièce XX est crée à partir de la pièce XXX , et la pièce XY et faite à partir de XYX et XYY, ce qui fait que si j'effectue une recherche sur la pièce X je me retrouve avec un tableaux de cette forme. (la colonne Issue est pas pertinente pour vous mais j'en ai besoin de mon coté)

    Pièce "Fille" | Pièce "Mère" | Issue | Level
    X | W | A00 | 0
    XX | X | A00 | 1
    XY | X | A00 | 1
    XXX | XX | A00 | 2
    XYX | XY | A00 | 2
    XYY | XY | A00 |2

    Mais je voudrais organiser mon tableaux par "bout" d'arborescence en clair comme ca

    Pièce "Fille" | Pièce "Mère" | Issue | Level
    X | W | A00 | 0
    XX | X |A00 | 1
    XXX| XX | A00 | 2
    XY | X | A00 | 1
    XYX | XY | A00 | 2
    XYY | XY | A00 | 2


    Si c'est pas clair n'hésitez pas à posez des questions mais je suis pas un très bon élève sur le site je garantie pas un réponse rapide
    Merci a ceux qui on pris le temps de lire et/ou répondre
    Gardez le feu brûlant dans votre cœur

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Une solution est de rajouter le "chemin", l'arborescence complète pour chaque pièce. Il ne reste ensuite qu'a trier selon ce chemin

    quelque chose dans ce genre (pas testé)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    WITH [Ttemp] (Part_No, Parent_No, Versioning, [level], chemin) AS 
    	(
    	--On sélectionne la pièces incriminer
    	SELECT Comp.Component_Part_No, Comp.Parent_Part_No, Comp.Component_Issue, 0 AS [level], Comp.Component_Part_No As chemin
    		FROM PARADEMODW.dbo.Components AS Comp
    		WHERE LTRIM(RTRIM(Comp.Component_Part_No)) = @PartVar AND RTRIM(LTRIM(Comp.Component_Issue)) LIKE '%'+@IssueVar+'%'
    		UNION ALL
    	--On sélectionne ensuite les pièces lié à la pièces incriminer
    	SELECT Comp.Component_Part_No, Comp.Parent_Part_No, Comp.Parent_Issue, [level] + 1, CONCAT(temp.chemin, '-', Comp.Component_Part_No)
    		FROM PARADEMODW.dbo.Components AS Comp
    		INNER JOIN Ttemp AS temp
    		ON LTRIM(RTRIM(Comp.Parent_Part_No)) = LTRIM(RTRIM(Temp.Part_No))
    		WHERE RTRIM(LTRIM(Comp.Parent_Issue)) = LTRIM(RTRIM(Temp.Versioning))
    	)
    --On affiche ensuite toutes les pièces sans les doublons
    SELECT DISTINCT * 
    	FROM Ttemp
    	ORDER BY chemin ASC

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 766
    Points : 52 561
    Points
    52 561
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,

    Une solution est de rajouter le "chemin", l'arborescence complète pour chaque pièce. Il ne reste ensuite qu'a trier selon ce chemin
    ça ne peut pas marcher... Cela s'appelle un "SIBLING" order

    Lisez l'article que j'ai écrit à ce sujet :
    https://blog.developpez.com/sqlpro/p...-intervallaire

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  4. #4
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour fred,

    j'ai lu ton article, mais il concerne la représentation intervallaire, ce qui n'est pas le cas ici.
    Par ailleurs, il n'explique pas pourquoi la solution que je propose ne "peut pas marcher".
    Cette solution peut même s'adapter au cas décrit dans ton article, en se passant de la fonction PADMASK, si on réécrit la dernière requête ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    WITH T0 AS 
    (SELECT VHC_ID, VHC_BG, VHC_BD, VHC_NIVEAU, VHC_NOM, 
            CAST(VHC_NOM AS NVARCHAR(max)) AS PATH_MIXTE
     FROM   T_VEHICULE_VHC
     WHERE  VHC_NIVEAU = 0
     UNION ALL
     SELECT T1.VHC_ID, T1.VHC_BG, T1.VHC_BD, T1.VHC_NIVEAU, T1.VHC_NOM, 
            CONCAT(T0.PATH_MIXTE , '-', T1.VHC_NOM)
     FROM   T_VEHICULE_VHC AS T1
            INNER JOIN T0
                   ON T1.VHC_NIVEAU = T0.VHC_NIVEAU + 1
                   AND T1.VHC_BG > T0.VHC_BG
                   AND T1.VHC_BD < T0.VHC_BD)
    SELECT CAST(SPACE(VHC_NIVEAU) + VHC_NOM AS VARCHAR(32)) AS NOM_IDENTE,
           VHC_ID, VHC_BG, VHC_BD, VHC_NIVEAU, PATH_MIXTE
    FROM   T0  
    ORDER  BY PATH_MIXTE;
    a priori, le tri est bien celui attendu non ?!

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 766
    Points : 52 561
    Points
    52 561
    Billets dans le blog
    5
    Par défaut
    Oui, il faut aligner la longueur de chacun des items du chemin... Mais cela grève les performances de façon catastrophique :
    1) requête récursive pour générer la colonne de tri
    2) colonne de tri énorme (dépassant parfois la longueur max autorisé pour les tris).
    Résultat : des performances merdiques...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Pour ce qui est de la requête récursive, elle l'est déjà pour récupérer l'arborescence complète.
    Et pour la limite de taille pour le tri, je ne vois pas de quoi tu parles, peux-tu préciser ?

    Enfin pour la question des performances, tout à fait d'accord, mais je pense qu'il n'y aura pas de solution efficace à ce problème.
    En fonction du besoin et de l'architecture et de la volumétrie globale, il sera peut-être préférable d'effectuer l'opération récursive et le tri coté client.

  7. #7
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 766
    Points : 52 561
    Points
    52 561
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Pour ce qui est de la requête récursive, elle l'est déjà pour récupérer l'arborescence complète.
    Et pour la limite de taille pour le tri, je ne vois pas de quoi tu parles, peux-tu préciser ?
    La limite de tri en octet est de 8 060.
    Enfin pour la question des performances, tout à fait d'accord, mais je pense qu'il n'y aura pas de solution efficace à ce problème.
    En fonction du besoin et de l'architecture et de la volumétrie globale, il sera peut-être préférable d'effectuer l'opération récursive et le tri coté client.
    On peut aussi utiliser le hierarchyid qui compresse le chemin et faire un tri dessus. J'ai jamais essayé !

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  8. #8
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2017
    Messages : 11
    Points : 11
    Points
    11
    Par défaut
    J'ai saisi la démarche rajouter l'ensemble des pièce a la suite et ranger notre tableaux grâce a cette concaténation de pièce mais je continue de recevoir un message d'erreur donc je saisi pas trop ce qui plante. J'ai 2 idée soit y a un petit soucis sur la requête, soit comme j'ai transférer tout mon travail de la BDD de dev à la BDD de l'entreprise et je m'y suis mal pris je vous link le message d'erreur tout de même lorsque je test la requête sur SSRS

    Nom : Capture.PNG
Affichages : 353
Taille : 7,3 Ko

    Merci encore a ceux qui file un coup de main

    MaJ : Dernière hypothèse c'est que le type qui se fait automatiquement sur chemin n'est pas adapté (Toutes mes colonnes sont normalement sous le format NVARCHAR(40))

  9. #9
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par Angry_Capitalist Voir le message
    MaJ : Dernière hypothèse c'est que le type qui se fait automatiquement sur chemin n'est pas adapté (Toutes mes colonnes sont normalement sous le format NVARCHAR(40))
    oui, c'est bien ça !

    dans l'ancrage de la requête récursive (première requête), il faut transtyper :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT Comp.Component_Part_No, Comp.Parent_Part_No, Comp.Component_Issue, 0 AS [level], CAST(Comp.Component_Part_No AS NVARCHAR(MAX)) As chemin

  10. #10
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2017
    Messages : 11
    Points : 11
    Points
    11
    Par défaut
    J'ai trouvé l'erreur il me manquait un CAST dans ma requete pour que tout colle
    Voila du coup la version finale pour les suivant qui tomberont sur ce post

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    WITH [Ttemp] (Part_No, Parent_No, Versioning, [level], chemin) AS 
    	(
    	--On sélectionne la pièces incriminer
    	SELECT Comp.Component_Part_No, Comp.Parent_Part_No, Comp.Component_Issue, 0 AS [level], CAST(Comp.Component_Part_No AS NVARCHAR(MAX)) As chemin
    		FROM PARADEMODW.dbo.Components AS Comp
    		WHERE LTRIM(RTRIM(Comp.Component_Part_No)) = @PartVar AND RTRIM(LTRIM(Comp.Component_Issue)) LIKE '%'+@IssueVar+'%'
    		UNION ALL
    	--On sélectionne ensuite les pièces lié à la pièces incriminer
    	SELECT Comp.Component_Part_No, Comp.Parent_Part_No, Comp.Parent_Issue, [level] + 1, CONCAT(temp.chemin, '-', CAST(Comp.Component_Part_No AS NVARCHAR(MAX)))
    		FROM PARADEMODW.dbo.Components AS Comp
    		INNER JOIN Ttemp AS temp
    		ON LTRIM(RTRIM(Comp.Parent_Part_No)) = LTRIM(RTRIM(Temp.Part_No))
    		WHERE RTRIM(LTRIM(Comp.Parent_Issue)) = LTRIM(RTRIM(Temp.Versioning))
    	)
    --On affiche ensuite toutes les pièces sans les doublons
    SELECT DISTINCT * 
    	FROM Ttemp
    	ORDER BY chemin ASC
    Merci a tous

  11. #11
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    La limite de tri en octet est de 8 060.
    Il y a bien une limite pour les indexes, mais par pour un ORDER BY à ma connaissance.

    En tout cas, un ORDER BY sur une colonne contenant du texte de plusieurs millions de caractères s'effectue sans erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    WITH T1 AS (
       SELECT CAST(REPLICATE('x', 8000) AS VARCHAR(MAX)) AS val
       UNION ALL
       SELECT CAST(CONCAT(val, REPLICATE('x', 8000)) AS VARCHAR(MAX))
       FROM T1
       WHERE LEN(val) < 10000000 --10 millions
    )
    SELECT val
    FROM T1
    ORDER BY val
    OPTION (MAXRECURSION 0)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Organisation d'une table FACT dans un BI
    Par pk93100 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 13/01/2017, 16h25
  2. [MPD] Organisation d'une table (clé-valeur ou classique ?)
    Par TeChn4K dans le forum Schéma
    Réponses: 2
    Dernier message: 02/11/2010, 09h49
  3. Organisation d'une table
    Par Nutaak dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 30/12/2007, 22h12
  4. Organisation d'une table
    Par Acti dans le forum Requêtes
    Réponses: 15
    Dernier message: 23/06/2006, 11h10
  5. [arborescence] jointure d'une table avec elle même ?
    Par Celelibi dans le forum Requêtes
    Réponses: 2
    Dernier message: 16/11/2004, 18h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo