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 :

Requete pere/fils selon type


Sujet :

Développement SQL Server

  1. #1
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut Requete pere/fils selon type
    Bonjour,

    J'ai une table une des enregistrements chainés :
    ID PERE TYPE LABEL
    1 null 'P' 'Prise'
    2 1 'L' 'Cable'
    3 2 'P' 'Aspirateur'


    Je cherche a avoir la chaine pour les enregistrements de type 'P' avec le pere de type 'P' precedent.

    Dans l'exemple, ca revient a obtenir :
    1 null
    3 1

    Mes connaissances en SQL etant un peu limitées, je bloque...

    Si quelqu'un à une idée de comment faire...

    Merci

  2. #2
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Bonsoir,

    Pouvez avoir une hiérarchie à plusieurs niveaux ou il existe un seul père pour un enfant dans votre cas ?

    ++

  3. #3
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Il n'y aurait qu'un pere pour un fils. Mais plusieurs fils pour un meme pere...

    Merci

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT M.ID,
    FROM   Matable AS M
           LEFT OUTER JOIN Matable AS P
                ON M.PERE = P.ID
    WHERE  M."TYPE" = 'P' 
      AND  P."TYPE" = 'P'
    Au passage intituler une colonne TYPE est une idiotie. TYPE est un mot clef de SQL !

    A lire : http://sqlpro.developpez.com/cours/s...age=partie1#L1

    A +

  5. #5
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Ok.

    Une solution :

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    DECLARE @T TABLE
    (
     ID INT,
     PERE INT,
     TYPE CHAR(1),
     LABEL VARCHAR(50)
    )
     
    INSERT @T VALUES (1, null, 'P', 'Prise')
    INSERT @T VALUES (2, 1, 'L', 'Cable')
    INSERT @T VALUES (3, 2, 'P', 'Aspirateur');
    INSERT @T VALUES (4, 1, 'P', 'Frigo');
    INSERT @T VALUES (5, 3, 'P', 'bille');
     
    WITH CTE (ID, TYPE, PERE, CHAINE)
    AS
    (
    	SELECT ID, TYPE, PERE, CAST('' AS VARCHAR(MAX))
    	FROM @T 
    	WHERE ID = 1
    	UNION ALL
        SELECT T.ID, T.TYPE, T.PERE, CAST(CTE.CHAINE + CAST(T.PERE AS CHAR(1)) + ' / ' AS VARCHAR(MAX)) 
    	FROM @T AS T
        INNER JOIN CTE
        ON T.PERE = CTE.ID
     
    )
    SELECT *
    FROM CTE
    WHERE TYPE = 'P'
    ORDER BY ID
    ++

  6. #6
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT M.ID,
    FROM   Matable AS M
           LEFT OUTER JOIN Matable AS P
                ON M.PERE = P.ID
    WHERE  M."TYPE" = 'P' 
      AND  P."TYPE" = 'P'
    Ce n'est pas le resultat voulu. Ca, ca ne sortira pas les liens dont le type des différent de 'P'.

    Citation Envoyé par SQLpro Voir le message
    Au passage intituler une colonne TYPE est une idiotie. TYPE est un mot clef de SQL !
    Bien sur, cette table n'est qu'un exemple simplifié de ma problématique (l'origine est le resultat d'une requete).


    Citation Envoyé par mikedavem Voir le message
    Ok.

    Une solution :

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    DECLARE @T TABLE
    (
     ID INT,
     PERE INT,
     TYPE CHAR(1),
     LABEL VARCHAR(50)
    )
     
    INSERT @T VALUES (1, null, 'P', 'Prise')
    INSERT @T VALUES (2, 1, 'L', 'Cable')
    INSERT @T VALUES (3, 2, 'P', 'Aspirateur');
    INSERT @T VALUES (4, 1, 'P', 'Frigo');
    INSERT @T VALUES (5, 3, 'P', 'bille');
     
    WITH CTE (ID, TYPE, PERE, CHAINE)
    AS
    (
    	SELECT ID, TYPE, PERE, CAST('' AS VARCHAR(MAX))
    	FROM @T 
    	WHERE ID = 1
    	UNION ALL
        SELECT T.ID, T.TYPE, T.PERE, CAST(CTE.CHAINE + CAST(T.PERE AS CHAR(1)) + ' / ' AS VARCHAR(MAX)) 
    	FROM @T AS T
        INNER JOIN CTE
        ON T.PERE = CTE.ID
     
    )
    SELECT *
    FROM CTE
    WHERE TYPE = 'P'
    ORDER BY ID
    ++
    J'ai essayé mais j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    1	P	NULL	
    3	P	2	1 / 2 / 
    4	P	1	1 / 
    5	P	3	1 / 2 / 3 /
    Donc le pere de 3 est 2 (et je voudrais 1)

  7. #7
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    J'ai modifié la requête pour prendre en compte le fait qu'il peut exister plusieurs parents. Il suffit ensuite de récupérer le 1er membre trouvé dans la chaîne pour chaque pièce .. si j'ai bien compris votre problème

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    DECLARE @T TABLE
    (
     ID INT,
     PERE INT,
     [TYPE] CHAR(1),
     LABEL VARCHAR(50)
    )
     
    INSERT @T VALUES (1, NULL, 'P', 'Prise')
    INSERT @T VALUES (2, 1, 'L', 'Cable')
    INSERT @T VALUES (3, 2, 'P', 'Aspirateur');
    INSERT @T VALUES (4, 1, 'P', 'Frigo');
    INSERT @T VALUES (5, 3, 'P', 'bille');
    INSERT @T VALUES (6, NULL, 'P', 'bille');
    INSERT @T VALUES (7, 6, 'P', 'Robinet');
    INSERT @T VALUES (8, 7, 'P', 'Boulon');
     
    WITH CTE (ID, [TYPE], PERE, CHAINE)
    AS
    (
    	SELECT ID, [TYPE], PERE, CAST('' AS VARCHAR(MAX))
    	FROM @T 
    	WHERE PERE IS NULL
    	UNION ALL
        SELECT T.ID, T.[TYPE], T.PERE, CAST(CTE.CHAINE + CAST(T.PERE AS CHAR(1)) + ' / ' AS VARCHAR(MAX)) 
    	FROM @T AS T
        INNER JOIN CTE
        ON T.PERE = CTE.ID
     
    )
    SELECT 
     ID, [TYPE], LEFT(CHAINE, 1)
    FROM CTE
    WHERE TYPE = 'P'
    ORDER BY ID
    ++

  8. #8
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Merci pour les reponses.

    Citation Envoyé par mikedavem Voir le message
    J'ai modifié la requête pour prendre en compte le fait qu'il peut exister plusieurs parents. Il suffit ensuite de récupérer le 1er membre trouvé dans la chaîne pour chaque pièce .. si j'ai bien compris votre problème

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    DECLARE @T TABLE
    (
     ID INT,
     PERE INT,
     [TYPE] CHAR(1),
     LABEL VARCHAR(50)
    )
     
    INSERT @T VALUES (1, NULL, 'P', 'Prise')
    INSERT @T VALUES (2, 1, 'L', 'Cable')
    INSERT @T VALUES (3, 2, 'P', 'Aspirateur');
    INSERT @T VALUES (4, 1, 'P', 'Frigo');
    INSERT @T VALUES (5, 3, 'P', 'bille');
    INSERT @T VALUES (6, NULL, 'P', 'bille');
    INSERT @T VALUES (7, 6, 'P', 'Robinet');
    INSERT @T VALUES (8, 7, 'P', 'Boulon');
     
    WITH CTE (ID, [TYPE], PERE, CHAINE)
    AS
    (
    	SELECT ID, [TYPE], PERE, CAST('' AS VARCHAR(MAX))
    	FROM @T 
    	WHERE PERE IS NULL
    	UNION ALL
        SELECT T.ID, T.[TYPE], T.PERE, CAST(CTE.CHAINE + CAST(T.PERE AS CHAR(1)) + ' / ' AS VARCHAR(MAX)) 
    	FROM @T AS T
        INNER JOIN CTE
        ON T.PERE = CTE.ID
     
    )
    SELECT 
     ID, [TYPE], LEFT(CHAINE, 1)
    FROM CTE
    WHERE TYPE = 'P'
    ORDER BY ID
    On se rapproche mais le resultat voulu, c'est le pere de type 'P' juste au dessus. Dans l'exemple, le pere de "Boulon" serait "Robinet" (la requete donnée renvoye le pere le plus haut, c'est a dire "bille").
    Mais l'idée de la requete recursive qui garde le pere est interessante, je vais creuser ca.

  9. #9
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    C'est bon, grace à vos reponses, j'ai pu faire la requete. Pour ceux que ca interesse :
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    DECLARE @T TABLE
    (
     ID INT,
     PERE INT,
     [TYPE] CHAR(1),
     LABEL VARCHAR(50)
    )
     
    INSERT @T VALUES (1, NULL, 'P', 'Prise')
    INSERT @T VALUES (2, 1, 'L', 'Cable')
    INSERT @T VALUES (3, 2, 'P', 'Aspirateur');
    INSERT @T VALUES (4, 3, 'P', 'Frigo');
    INSERT @T VALUES (5, 3, 'P', 'bille');
    INSERT @T VALUES (6, NULL, 'P', 'bille');
    INSERT @T VALUES (7, 6, 'P', 'Robinet');
    INSERT @T VALUES (8, 7, 'P', 'Boulon');
     
    WITH CTE (ID, [TYPE], PERE, CHAINE)
    AS
    (
    	SELECT ID, [TYPE], PERE, NULL
    	FROM @T 
    	WHERE PERE IS NULL
    	UNION ALL
        SELECT T.ID, T.[TYPE], T.PERE, CASE CTE.[TYPE] WHEN 'P' THEN CTE.ID ELSE CTE.PERE END
    	FROM @T AS T
        INNER JOIN CTE
        ON T.PERE = CTE.ID
     
    )
    SELECT 
     CTE.ID, CTE.TYPE, CTE.CHAINE
    FROM CTE
    ORDER BY ID
    Tant qu'à etre la, est ce que quelqu'un saurait si, en terme de ressources, une requete recursive de ce type est beaucoup plus couteuse qu'une requete simple ?
    Parce que dans mon cas, je me posais la question de filter directement les installation de type different de 'P' par SQL ou par programme...

Discussions similaires

  1. Recherche dans XMLTYPE de PERE/FILS de type 0..n
    Par Hobbi1 dans le forum Oracle
    Réponses: 2
    Dernier message: 28/05/2013, 10h05
  2. Requete récursive pere-fils
    Par gloubi dans le forum Requêtes
    Réponses: 5
    Dernier message: 25/02/2008, 15h22
  3. Conversion type fils dans type pere
    Par Dr@ke dans le forum Langage
    Réponses: 6
    Dernier message: 08/11/2007, 17h36
  4. Réponses: 6
    Dernier message: 08/11/2005, 20h33
  5. Réponses: 3
    Dernier message: 17/05/2004, 18h28

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