Précédent   Forum des professionnels en informatique > Bases de données > PostgreSQL > Requêtes
Requêtes Forum d'entraide sur les requêtes SQL spécifiques à PostgreSQL, les triggers, les vues, etc.
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 31/08/2011, 19h51   #1
Nouveau Membre du Club
 
Inscription : mai 2005
Messages : 64
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 64
Points : 34
Points : 34
Par défaut Join et conditions

Salut tout le monde,

J'ai un problème de requete à base de JOIN que je souhaite élucider, mais je n'y arrive pas.

J'ai deux tables, reliées par une table pivot :

Code :
1
2
3
4
5
6
7
8
 
---------        ----------------        ---------        
|objects|        |labels_objects|        |labels |
---------        ----------------        ---------
|id     |        |label_id      |        |id     |
|datas  |        |object_id     |        |type   |
---------        ----------------        |datas  |
                                         ---------
Rien de compliqué, on a des objets, des étiquettes, et on met des étiquettes sur les objets. C'est une relation n-n, un objet peut avoir plusieurs étiquettes et une étiquette peut estampiller plusieurs objets.

Attention c'est là que ca se complique :

Je travaille sur les objets. Je souhaite récupérer la liste des objets, et quand il y a une etiquette de type "rouge" sur un objet, je souhaite récupérer l'étiquette. Quand il n'y a pas d'étiquettes, je souhaite récupérer l'objet quand meme.

Pour cela je procède de la façon suivante.
Code :
1
2
3
4
 
SELECT objects.id AS oid, labels.id AS lid, labels.type FROM objects
LEFT JOIN labels_objects ON (labels_objects.object_id = objects.id)
LEFT JOIN labels ON (labels.id = labels_objects.label_id AND type = 'rouge');
Certains voient déjà peut etre le problème se profiler :

Je récupère bien tout ce que je veux, mais si des objets appartiennent à plusieurs labels, rouge ou non, et bien je récupère ces objets mais en de multiples exemplaires ! Je vais donner un exemple pour illustrer :

Code :
1
2
3
4
5
6
7
8
9
10
 
-----------------        -----------------------            -------------------------
|    objects    |        |   labels_objects    |            |       labels          |
-----------------        -----------------------            -------------------------
|id       datas |        |label_id    object_id|            |id       type     datas|
|---------------|        |---------------------|            |-----------------------|
|1        pomme |        |1           1        |            |1        rouge    0x53 |    
|2        poire |        |1           2        |            |2        vert     0x58 |
|3        banane|        |2           2        |            -------------------------
-----------------        -----------------------
Le résultat de la requete précédente :
(j'ai ajouté lalid qui correspond à labels_objects.label_id, pour qu'on pige bien le pb)
Code :
1
2
3
4
5
6
7
8
9
 
------------------------------------
|oid     lid     lalid        type |
------------------------------------
|1       1       1            rouge|
|1       NULL    2            NULL |
|2       NULL    2            NULL |
|3       NULL    NULL         NULL |
------------------------------------
Ce qui m'embete c'est le deuxieme rang, je voudrais le dégager. Cela vient du JOIN sur la table labels_objects. J'aimerai m'en défaire sans avoir recours à trop de de conditions WHERE car l'exemple est bien plus simple que la réalité, et je m'en sors pas avec des where à ralloooooonge : _ AND ( ( _ AND _ ) OR _ ) ... Je veux aussi éviter les DISTINCT ON () aussi car je ne maitrise pas bien le rang qu'il choisit de me remonter, parfois j'ai celui avec l'étiquette, parfois non !

Voyez vous une solution, idéalement à placer sur le JOIN, qui me permettrai de résoudre ce problème ?

Merci d'avance !

Bonne soirée.

Guiz

PS : pour les courageux, voici les scripts CREATE afin de reproduire l'exemple. Par souci de simplicité, toutes les
relations ne figurent pas. Les inserts sont a faire à la main, mais bon, c'est vraiment pas long.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
CREATE TABLE labels
(
  id serial NOT NULL,
  "type" character varying,
  datas character varying,
  CONSTRAINT labels_pkey PRIMARY KEY (id)
)
 
CREATE TABLE labels_objects
(
  label_id integer NOT NULL,
  object_id integer NOT NULL,
  CONSTRAINT labels_objects_pkey PRIMARY KEY (label_id, object_id)
)
 
CREATE TABLE objects
(
  id serial NOT NULL,
  datas character varying,
  CONSTRAINT objects_pkey PRIMARY KEY (id)
)
ZeGuizmo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/08/2011, 21h35   #2
Rédacteur/Modérateur
 
Avatar de David55
 
Homme David S.
Etudiant en alternance
Inscription : août 2010
Messages : 1 167
Détails du profil
Informations personnelles :
Nom : Homme David S.
Âge : 22
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Etudiant en alternance
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : août 2010
Messages : 1 167
Points : 2 304
Points : 2 304
Bonsoir,

Qu'est ce qui t’empêche de faire un INNER JOIN?
__________________
Vous trouverez ma page perso avec des tutoriels sur Android et BIRT au lien suivant : http://dsilvera.developpez.com
N'oubliez pas de voter pour les messages dont la réponse est pertinente (en bas à droite du cadrant)
Vous voulez afficher du code :
Votre problème est résolu :
Pas de question technique par MP !
David55
David55 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/08/2011, 21h58   #3
Nouveau Membre du Club
 
Inscription : mai 2005
Messages : 64
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 64
Points : 34
Points : 34
J'ai peur de dire une bêtise là mais un inner join ne va pas me sélectionner les objets qui n'ont aucun label, si ?
ZeGuizmo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/09/2011, 10h04   #4
Nouveau Membre du Club
 
Inscription : mai 2005
Messages : 64
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 64
Points : 34
Points : 34
Salut,

Je confirme ma réponse d'hier soir, je ne comprends pas comment un INNER JOIN pourrait sélectionner les lignes qui ne remplissent pas forcément la condition. Si tu as une explication n'hésite pas à me la fournir.

Néanmoins, merci pour ta réponse.
ZeGuizmo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/09/2011, 10h22   #5
Nouveau Membre du Club
 
Inscription : mai 2005
Messages : 64
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 64
Points : 34
Points : 34
Je viens de trouver une solution qui pourrait répondre à mon problème, c'est d'utiliser des subqueries dans le JOIN (c'est peut etre ce que David55 suggérait). Je ne savais même pas que ça se faisait :

Code :
1
2
3
4
SELECT objects.id AS oid, temp.id AS lid, temp.type FROM objects
LEFT JOIN 	
	(SELECT labels.id, labels.type, labels_objects.object_id FROM labels_objects JOIN labels ON (labels.id = labels_objects.label_id)) temp 
ON (objects.id = temp.object_id AND temp.type = 'rouge')
Je réfléchi encore un peu, et si je ne trouve pas mieux je placerai cela en résolu. En attendant je suis toujours ouvert à vos commentaires.

Merci
ZeGuizmo est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/09/2011, 16h51   #6
Modérateur
 
Inscription : octobre 2008
Messages : 1 508
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2008
Messages : 1 508
Points : 2 040
Points : 2 040
Tu peux aussi faire:
SELECT des objets ayant un label rouge
UNION
SELECT des objets n'ayant aucun label

Pour les objets n'ayant aucun label, c'est requêtable avec une clause NOT IN, ou bien avec un objects LEFT JOIN label_objects et condition IS NULL sur la colonne de jointure.
estofilo est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 02/09/2011, 09h57   #7
Nouveau Membre du Club
 
Inscription : mai 2005
Messages : 64
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 64
Points : 34
Points : 34
Finalement je suis très satisfait de ma méthode. Mes requêtes ne sont pas beaucoup plus complexes, et cela fonctionne très bien !

estofilo, ta solution fonctionne, mais m'oblige à taper deux requêtes de sélection. Je préfère donc la mienne.

Merci pour vos réponses.
ZeGuizmo est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h50.


 
 
 
 
Partenaires

Hébergement Web