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 13/12/2010, 18h37   #1
Membre émérite
 
Inscription : mai 2006
Messages : 787
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 787
Points : 837
Points : 837
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
hwoarang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/12/2010, 18h40   #2
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 723
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 723
Points : 6 844
Points : 6 844
Bonsoir,

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

++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/12/2010, 14h51   #3
Membre émérite
 
Inscription : mai 2006
Messages : 787
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 787
Points : 837
Points : 837
Il n'y aurait qu'un pere pour un fils. Mais plusieurs fils pour un meme pere...

Merci
hwoarang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/12/2010, 15h25   #4
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 950
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 950
Points : 17 766
Points : 17 766
Code :
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 +
__________________
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
Vieux 14/12/2010, 15h37   #5
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 723
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 723
Points : 6 844
Points : 6 844
Ok.

Une solution :

Code :
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
++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/12/2010, 17h33   #6
Membre émérite
 
Inscription : mai 2006
Messages : 787
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 787
Points : 837
Points : 837
Citation:
Envoyé par SQLpro Voir le message
Code :
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 :
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 :
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)
hwoarang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/12/2010, 19h48   #7
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 723
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 723
Points : 6 844
Points : 6 844
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 :
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
++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/12/2010, 09h34   #8
Membre émérite
 
Inscription : mai 2006
Messages : 787
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 787
Points : 837
Points : 837
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 :
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.
hwoarang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/12/2010, 10h08   #9
Membre émérite
 
Inscription : mai 2006
Messages : 787
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 787
Points : 837
Points : 837
C'est bon, grace à vos reponses, j'ai pu faire la requete. Pour ceux que ca interesse :
Code :
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...
hwoarang 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 00h37.


 
 
 
 
Partenaires

Hébergement Web