Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD
PHP & SGBD Forum d'entraide sur les SGBD avec PHP. Avant de poster : FAQ BDD, toutes les FAQ PHP, cours BDD et sources BDD
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/08/2006, 11h31   #1
Membre émérite
 
Avatar de guitou12
 
Guillaume
Inscription : juillet 2006
Messages : 813
Détails du profil
Informations personnelles :
Nom : Guillaume
Âge : 29

Informations forums :
Inscription : juillet 2006
Messages : 813
Points : 905
Points : 905
Envoyer un message via MSN à guitou12
Par défaut [SQL] Pb conditions sur tables multiples

Bonjour, j'ai un petit de souci de requête comme vous pouviez vous en douter.

Voilà le schéma simplifié de mes tables.
Table user : nom,prenom,iduser

Table groupe : idgroupe, nom

Table messages : idmess, iduser, idgroupe, texte


Sachant qu'un message peut être adressé SOIT à un user (iduser != -1 et idgroupe = -1) SOIT à un groupe (idgroupe != -1 et iduser = -1) je cherche à récupérer suivant les cas

-> Le nom du groupe (si c'est destiné au groupe)
ou bien
-> Les noms et prénoms de l'utilisateur (si c'est destiné à l'utilisateur)

J'ai tenté avec un case mais sans succès....

Un coup de main serait le bienvenue,

en vous remerciant par avance.
__________________
Le . est la base de toute bonne concaténation, marre de voir des
echo "Mavar1 = $toto et Mavar2 = $titi";
ou pire echo 'Mavar1 = ',$toto,' et Mavar2 = ',$titi;
pratiquez plutôt le echo 'Mavar1 = '.$toto.' et Mavar2 = '.$titi;
guitou12 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/08/2006, 11h54   #2
Membre éclairé
 
Avatar de DBProg
 
Étudiant
Inscription : juillet 2006
Messages : 242
Détails du profil
Informations personnelles :
Âge : 27
Localisation : France, Moselle (Lorraine)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juillet 2006
Messages : 242
Points : 315
Points : 315
Salut !

Je te propose une solution qui fonctionne, mais elle n'est pas très optimisée (du moins je pense). Je suis également ouvert à toute optimisation, je ne connais pas trop les CASE en SQL encore.

Code :
1
2
3
4
SELECT M.idmess, M.texte, IF(M.iduser IS NULL, (
SELECT idgroupe, nom FROM groupe G WHERE G.idgroupe = M.idgroupe),
(SELECT iduser, nom, prenom FROM user U WHERE U.iduser = M.iduser))
FROM messages M
Comme tu peux le constater j'ai utilisé IS NULL pour la condition. Car en fait je te conseille de mettre l'une des deux valeurs (celle qui n'est pas renseignée) à NULL et non à -1. C'est plus propre, et c'est fait pour !
__________________
La vitesse de la lumière étant supérieure à la vitesse du son, certaines personnes brillent encore tant qu'elles n'ont pas parlé
-----------------------------------------------------------
Retrouvez mes articles informatique sur mon Site Developpez.
Le reste, sur le Site perso !

DBProg est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/08/2006, 12h07   #3
Membre habitué
 
Inscription : octobre 2003
Messages : 102
Détails du profil
Informations personnelles :
Âge : 39

Informations forums :
Inscription : octobre 2003
Messages : 102
Points : 108
Points : 108
Re-salut :-)

un UNION me semble tout indiqué.
Code :
1
2
3
4
 
SELECT nom, prenom, texte FROM messages JOIN user USING(iduser)
UNION
SELECT nom, '/' as 'prenom', texte FROM messages JOIN groupe USING(idgroupe)
remarque que je triche un peu pour le groupe en créant un pseudo champ prenom dans la requete (je mets arbitrairement la valeur "/") afin de calquer la structure de cette requete sur la premiere pour que le UNION marche.


Si tu peux créer à la volée pour chaque ligne l'info type de destinataire en créant également le pseudoi champ 'type_detin'
remarque que structurellement parlant, les différentes requetes qui composent le UNION doivent rester "superposables" (même champs et dans le même ordre):

Code :
1
2
3
4
 
SELECT 'Utilisateur' AS 'type_dest', 'nom, prenom, texte FROM messages JOIN user USING(iduser)
UNION
SELECT 'Groupe' AS 'type_dest', nom, '/' as 'prenom', texte FROM messages JOIN groupe USING(idgroupe)
Bon et le fin du fin, si tu veux garder la possibilité de brasser, ordonner, grouper etc. les resultats dans leur globalité (par ex pas de clause order pour UNION), et si ton serveur SQL est > 4.1 (je te guarantie rien pour les versions plus anciennes)
Tu peux faire comme si cette requete audessus était une table que tu peux manipuler (classer par nom par exemple) en fait :

Code :
1
2
3
4
5
6
7
8
 
SELECT type_dest, nom, prenom, texte FROM
(
SELECT 'Utilisateur' AS 'type_dest', nom, prenom, texte FROM messages JOIN user USING(iduser)
UNION
SELECT 'Groupe' AS 'type_dest', nom, '/' as 'prenom', texte FROM messages JOIN groupe USING(idgroupe)
) AS DERIVED_TABLE
ORDER BY nom
sans aller jusqu'a la sophistication de la dernière pense toujours a ca : les requetes (autant que tu veux en fait) reliées par un UNION doivent être toutes superposables en structures.


Table user : nom,prenom,iduser

Table groupe : idgroupe, nom

Table messages : idmess, iduser, idgroupe, texte
__________________
il n'y a pas de sotte existence
gisele est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/08/2006, 13h32   #4
Membre émérite
 
Avatar de guitou12
 
Guillaume
Inscription : juillet 2006
Messages : 813
Détails du profil
Informations personnelles :
Nom : Guillaume
Âge : 29

Informations forums :
Inscription : juillet 2006
Messages : 813
Points : 905
Points : 905
Envoyer un message via MSN à guitou12
Alors une petite précision pour rajouter un peu de piment (sinon c'est définitivement pas marrant hein )

Je ne peux pas mettre mes champs à NULL étant donné que c'est une base utilisée par un soft et que celui qui en a fait la conception devait pas être bien réveillé ce jour là. Donc en résumé TOUS les champs doivent être remplis alors pour gruger ils calent des espaces dans les champs qui ne contienent rien.

Ensuite pour la version SQL>4.1 aucune idée étant donné que je suis sous Oracle8i

Je vais tester avec la version de Gisele mais il faut que j'arrive à tout piger

EDIT : j'ai testé et ... ça ne fonctionne pas

Voilà ma requête (inspirée de la 1ère de gisele) avec les vrais noms de champs (attention ça fait mal aux yeux)

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 SELECT 
USR_0,  // iduser (table AUTILIS & XMESSAGES) --> -1 ou valeur
NOMUSR_0, // nom (table AUTILIS)
PRENOMUSR_0,  // prenom (table AUTILIS)
XCHRONO_0, // index message (table XMESSAGE)
TEXTE_0, // texte message (table XMESSAGE)
GROUPE_0, // groupe destinataire (table XMESSAGE) --> -1 ou valeur
INTITDROIT_0 // nom du groupe (table XDROITS)
   FROM XMESSAGES JOIN AUTILIS USING(USR_0)
WHERE XCHRONO_0=1
UNION 
  SELECT 
USR_0, 
NOMUSR_0, 
'/' AS 'PRENOMUSR_0', 
XCHRONO_0, 
TEXTE_0, 
GROUPE_0, 
INTITDROIT_0 
  FROM XMESSAGES JOIN XDROITS USING (GROUPE_0)
WHERE XCHRONO_0=1
J'ai pas bien compris l'histoire du / as prenom non plus

Merci de m'éclairer de vos lumières et de prendre le temps de me répondre
__________________
Le . est la base de toute bonne concaténation, marre de voir des
echo "Mavar1 = $toto et Mavar2 = $titi";
ou pire echo 'Mavar1 = ',$toto,' et Mavar2 = ',$titi;
pratiquez plutôt le echo 'Mavar1 = '.$toto.' et Mavar2 = '.$titi;
guitou12 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/08/2006, 13h49   #5
Membre habitué
 
Inscription : octobre 2003
Messages : 102
Détails du profil
Informations personnelles :
Âge : 39

Informations forums :
Inscription : octobre 2003
Messages : 102
Points : 108
Points : 108
bah si si t'as la main sur ta base genre avec phpmyadmin, clique sur SQL et patate une des requetes, elles sont pretes pour l'emploi.

Pour etre plus clair, UNION sert à cumuler les resultats de 2 ou plusieurs requetes a conditions qu'elles aient la même gueule. (memes noms/structures de champs dans la clause SELECT)

par exemple, je cumule dans le même jeu d'enregistrement

un select sur les messages des user + un select sur lesmessages des groupes

mon premier ex , le plus simple renvoie tous les message pour user suivi de tous le smessages pour groupe, en comblant le champ 'prenom' avec "/" pour le cas groupe.


Mon 2 eme exemple ajoute un champs qui stipule quel type dedestinataire
en terme de retour ca afficherait quelque chose comme çà:

type_dest | nom | prenom | message
Utilisateur | DUPOND | paul | son_messageblablasdfsd
Utilisateur | Janvion | Gerard| son_messageblabla_a_gerard
Utilisateur |Zimako | Jacques | son_messageblablahdskjfhsd
Groupe |groupe1| / | son_messageblabla_au_groupe1
Groupe |groupe2 |/ |son_messageblablahdskjfhsd_groupe2

Mon 2 eme exemple englobe ces resultat dans une pseudo table formée par une sousrequete (la meme que l'exemple 2) de maniere a pouvoir manipuler la table (ORDER BY, GROUP BY etc.), chose impossible avec dans chacune des requetes UNION.

je classe par nom les resultat au dessus (order by nom) et ca donne :

type_dest | nom | prenom | message
Utilisateur | DUPOND | paul | son_messageblablasdfsd
Groupe |groupe1| / | son_messageblabla_au_groupe1
Groupe |groupe2 |/ |son_messageblablahdskjfhsd_groupe2
Utilisateur | Janvion | Gerard| son_messageblabla_a_gerard


remarque : d'apres ce que tu me dit dans ton dernier post, tu peux rempacer '/' par NULL (sans les quotes) pour obtenir des champs vides.
Utilisateur |Zimako | Jacques | son_messageblablahdskjfhsd
__________________
il n'y a pas de sotte existence
gisele 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 13h01.


 
 
 
 
Partenaires

Hébergement Web