Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server > Développement
Développement Forum d'entraide sur le Transact-SQL, le CLR, les procédures stockées, les triggers, les requêtes SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 04/01/2012, 17h13   #1
Membre du Club
 
Inscription : mars 2002
Messages : 98
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 98
Points : 55
Points : 55
Par défaut Requête récursive, éviter de traiter plusieurs fois un même "couple" père-fils

Bonjour.
J'ai lu avec très grand intérêt l'article de F. Brouard sur les requêtes récursives.
http://sqlpro.developpez.com/cours/s...te-recursives/

J'ai fait une requête récursive qui me renvoie la liste d'éléments père-fils qui se trouvent dans une table TRACABILITE.
Voici la requête:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
WITH    tree (DATA, nom_pere, nom_fils)
AS (SELECT volume_assemble, nom_lot_pere, Nom_lot_fils
    FROM   TRACABILITE
    WHERE  Nom_lot_fils=6464
    UNION ALL                            
    SELECT volume_assemble, nom_lot_pere    , Nom_lot_fils
    FROM   TRACABILITE V                  
           INNER JOIN tree t 
                 ON t.nom_pere = V.Nom_lot_fils)
SELECT *
FROM   tree
ORDER BY nom_fils DESC
OPTION (MAXRECURSION 32000);

Dans la section IV-B.1, il semble expliquer comment éviter de traiter plusieurs fois les couples père-fils identiques. Je ne comprends pas cette partie... Du coup quand j'exécute ma requête, je me retrouve avec des branches de ma traçabilité qui s'affichent plusieurs fois. Cela est du à la nature de mes données, et c'est normal. Dans l'ancien code que j'utilisais, je ne traitais pas un couple père-fils que j'avais déjà traité.
Savez-vous comment je dois ajouter la clause WHERE dans la requête pour qu'il ne traite pas plusieurs fois un même couple père-fils?

Suis-je clair?

Merci
sbeu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/01/2012, 19h42   #2
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 686
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 686
Points : 10 435
Points : 10 435
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
J'ai une solution, mais probablement pas optimale, et limitée.

L'idée c'est de concaténer la PK de votre table dans une colonne avec un séparateur et de vérifier quand vous parcourez votre arborescence que vous n'êtes pas déjà passé par cette ligne.

Quelque chose de ce type :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
WITH tree (DATA, nom_pere, nom_fils, parcours) AS
(
SELECT volume_assemble, nom_lot_pere, Nom_lot_fils
     , '#' + cast(<PK> AS varchar(max)) + '#'
  FROM dbo.TRACABILITE
 WHERE Nom_lot_fils = 6464
 UNION ALL                            
SELECT V.volume_assemble, V.nom_lot_pere, V.Nom_lot_fils
     , t.parcours + cast(V.<PK> AS varchar) + '#'
  FROM dbo.TRACABILITE AS V                  
       INNER JOIN tree AS t 
         ON t.nom_pere = V.Nom_lot_fils
 WHERE charindex('#' + cast(V.<PK> AS varchar) + '#', t.parcours) = 0
)
  SELECT DATA, nom_pere, nom_fils
    FROM tree
ORDER BY nom_fils DESC
OPTION (MAXRECURSION 32000);
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2012, 14h54   #3
Membre du Club
 
Inscription : mars 2002
Messages : 98
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 98
Points : 55
Points : 55
Par défaut Après tests

Bonjour,
Merci pour ta réponse

Je viens d'essayer, et ça ne marche pas...
Je n'avais pas de colonne PK donc j'en ai créé une, avec dedans, un numéro auto.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
WITH tree (DATA, nom_pere, nom_fils, parcours) AS
(
SELECT volume_assemble, nom_lot_pere, Nom_lot_fils, cle_unique
  FROM dbo.TRACABILITE
 WHERE Nom_lot_fils = 6464 
 UNION ALL                            
SELECT V.volume_assemble, V.nom_lot_pere, V.Nom_lot_fils,cle_unique
  FROM dbo.TRACABILITE AS V                  
       INNER JOIN tree AS t 
         ON t.nom_pere = V.Nom_lot_fils
 WHERE cle_unique <> t.parcours
)
  SELECT DATA, nom_pere, nom_fils, parcours
    FROM tree
ORDER BY nom_fils DESC
OPTION (MAXRECURSION 32000);
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
WITH tree (DATA, nom_pere, nom_fils, parcours) AS
(
SELECT volume_assemble, nom_lot_pere, Nom_lot_fils, '#' + cast(cle_unique AS varchar(max)) + '#'
  FROM dbo.TRACABILITE
 WHERE Nom_lot_fils = 6464 
 UNION ALL                            
SELECT V.volume_assemble, V.nom_lot_pere, V.Nom_lot_fils,'#' + cast(cle_unique AS varchar(max)) + '#'
  FROM dbo.TRACABILITE AS V                  
       INNER JOIN tree AS t 
         ON t.nom_pere = V.Nom_lot_fils
 WHERE  charindex('#' + cast(cle_unique AS varchar) + '#', t.parcours) = 0
)
  SELECT DATA, nom_pere, nom_fils, parcours
    FROM tree
ORDER BY nom_fils DESC
OPTION (MAXRECURSION 200);
J'ai essayé aussi en faisant un CAST, comme dans ta réponse.
Est-ce quelquechose que tu as déjà pratiqué? L'arrêt du calcul de la récursivité?
sbeu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2012, 17h13   #4
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 959
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 959
Points : 17 791
Points : 17 791
Citation:
Envoyé par sbeu Voir le message
Bonjour.
J'ai lu avec très grand intérêt l'article de F. Brouard sur les requêtes récursives.
http://sqlpro.developpez.com/cours/s...te-recursives/

J'ai fait une requête récursive qui me renvoie la liste d'éléments père-fils qui se trouvent dans une table TRACABILITE.
Voici la requête:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
WITH    tree (DATA, nom_pere, nom_fils)
AS (SELECT volume_assemble, nom_lot_pere, Nom_lot_fils
    FROM   TRACABILITE
    WHERE  Nom_lot_fils=6464
    UNION ALL                            
    SELECT volume_assemble, nom_lot_pere    , Nom_lot_fils
    FROM   TRACABILITE V                  
           INNER JOIN tree t 
                 ON t.nom_pere = V.Nom_lot_fils)
SELECT *
FROM   tree
ORDER BY nom_fils DESC
OPTION (MAXRECURSION 32000);

Dans la section IV-B.1, il semble expliquer comment éviter de traiter plusieurs fois les couples père-fils identiques. Je ne comprends pas cette partie... Du coup quand j'exécute ma requête, je me retrouve avec des branches de ma traçabilité qui s'affichent plusieurs fois. Cela est du à la nature de mes données, et c'est normal. Dans l'ancien code que j'utilisais, je ne traitais pas un couple père-fils que j'avais déjà traité.
Savez-vous comment je dois ajouter la clause WHERE dans la requête pour qu'il ne traite pas plusieurs fois un même couple père-fils?

Suis-je clair?

Merci
Lisez jusqu'au bout mon papier, et vous verrez que la requête 24 correspond à votre demande. En effet en concaténant le chemin on peut éviter de prendre en compte une deuxième fois un même item.

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 04h03.


 
 
 
 
Partenaires

Hébergement Web