Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1665 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [resolu]Besoin d'aide pour jointure sur mySQL

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[resolu]Besoin d'aide pour jointure sur mySQL

n°1620603
Halike
Posté le 08-10-2007 à 15:44:00  profilanswer
 

Bonjour à tous,
 
Je vais essayer de décrire mon probleme:
J'ai une table 'objets', qui possede deux colonnes : id et description.
J'ai  une table users,qui possede aussi deux colonnes: id et name.
Enfin,j'ai une table historique, qui possede 4 colonnes: id_user, id_objet, type_action et date.
Cette derniere table va enfait enregistrer les actions des utilisateurs sur les objets, sachant qu'il y a différents types d'actions, représentés par des nombres.
Pour chaque action, on enregistre donc l'id de l'utilisateur,l'id de l'objet, la date et le type de l'action.
 
Je voudrais récupérer la liste de tous les objets, avec pour chaque objet, le nom de l'utilisateur qui a effectué l'action de type N sur cet objet.
Là ou ca se corse, c'est que l'action N peut avoir été effectuée plusieurs fois, et par des utilisateurs différents (je précise que l'action N a été effectuée au moins une fois), et je voudrais récupérer le premier utilisateur ayant effectué l'action (premier au sens temporel).
Voici mes différents essais:

Code :
  1. SELECT o.id,o.description,h.date,u.name
  2. FROM objets AS o,
  3. INNER JOIN (SELECT id_user,id_objet FROM historique WHERE type_action=N) h
  4. ON h.id_objet=o.id
  5. INNER JOIN users AS u
  6. ON u.id=h.id_user


 
->Probleme: retourne des doublons quand plusieurs utilisateurs ont effectué l'action N sur un objet.
Pour corriger ce probleme de doublons, j'ai tenté un truc:

Code :
  1. SELECT o.id,o.description,h.date,u.name
  2. FROM objets AS o,
  3. INNER JOIN (SELECT id_user,id_objet FROM historique WHERE type_action=N LIMIT 1) h
  4. ON h.id_objet=o.id
  5. INNER JOIN users AS u
  6. ON u.id=h.id_user


->Apres m'etre demandé pourquoi cette requete ne retournait rien, je me suis vite rendu compte que j'avais fait n'importe quoi avec mon "LIMIT", et que c'était normal.
 
 
En dernier recours, je suppose que je pourrais post-filtrer le resultat de la requete 1 avec PHP, mais l'idée ne me plait pas beacoup...
Je pense qu'il doit y avoir moyen de faire faire ca à mySQL, mais ca me dépasse un peu.
 
Des idées?
 
Merci et bonne journée :)


Message édité par Halike le 09-10-2007 à 12:39:09
mood
Publicité
Posté le 08-10-2007 à 15:44:00  profilanswer
 

n°1620736
mrbebert
Posté le 08-10-2007 à 22:15:03  profilanswer
 

On va être méthodique :
- 1ère sous-requête qui récupère pour chaque id_objet la date min pour l'action recherchée (on va dire que c'est la 123), qu'on va appeller tb_A dans la requête
- jointure vers la table historique pour récupérer l'id de l'utilisateur
- jointure vers la table users pour récupérer son nom
- jointure vers la table objets pour récupérer son nom
 
Et pour le cas où il n'y aurait pas d'action effectuée, on protège les champs correspondants par un IFNULL
 
C'est parti :o  
 
SELECT objets.name, IFNULL(tb_A.dmin, '0000-00-00') date, IFNULL(users.name, '') user_name
FROM
  (SELECT id_objet, min(date) dmin
  FROM historique
  WHERE type_action=123
  GROUP BY id_objet) tb_A
LEFT JOIN historique ON tb_A.id_objet=historique.id_objet AND tb_A.dmin=historique.date
LEFT JOIN users ON historique.id_user=users.id
LEFT JOIN objets ON tb_A.id_objet=objets.id
 
Aux fautes prêts, je pense que ca devrait renvoyer un résultat pas trop éloigné de ce que tu recherches [:figti]  
 
(mais je suis étonné de ne pas trouver plus simple :??: )


Message édité par mrbebert le 08-10-2007 à 22:16:22
n°1620978
Halike
Posté le 09-10-2007 à 12:38:33  profilanswer
 

Yes! :)
Merci beaucoup, ca fonctionne.
J'ai fait un truc de ce style:
SELECT o.id,o.description,u.name,h.date
FROM (SELECT id_objet,id_user,MIN(date) FROM historique WHERE type_action=123 GROUP BY id_objet) h
INNER JOIN users u ON u.id=h.id_user
INNER JOIN objets o ON o.id=h.id_objet

 
Ca semble fonctionner.
 
Encore Merci.
 
Bonne journée :)
 
Edit: Voir message en dessous...


Message édité par Halike le 09-10-2007 à 15:02:28
n°1620982
mrbebert
Posté le 09-10-2007 à 13:01:23  profilanswer
 

FAUX !!!!!!!!!!!!!!!!!! :D  
 
Quand tu mets :
SELECT id_objet, id_user, MIN(date) FROM historique ...
Qu'est-ce qui te garantit que le id_user qui est fourni est bien celui qui correspond à la date minimale ?
 
(réponse : rien :o  [:proy] )

n°1621088
Halike
Posté le 09-10-2007 à 15:06:17  profilanswer
 

:ange:  
Arf. Mais bien sur.
 
Il aurait été marrant à débugger celui la...
Du coup, re-merci, et re-résolu :)

n°1621276
MagicBuzz
Posté le 09-10-2007 à 17:47:08  profilanswer
 

FROM objets AS o,
=> vire la ","
 
pour le reste pas lu le topic.
je suis tout naze.
 
on a le droit de faire une jointure sur un sous-select.
par contre je vois pas trop l'intérêt dans ton cas, je suis pas sûr que ton limit apporte quand chose niveau perfs.
rien que pour la lisibilité, tu ferais mieux de faire une belle jointure régulière.


Message édité par MagicBuzz le 09-10-2007 à 17:47:27
n°1621278
MagicBuzz
Posté le 09-10-2007 à 17:49:34  profilanswer
 

mrbebert a écrit :

FAUX !!!!!!!!!!!!!!!!!! :D  
 
Quand tu mets :
SELECT id_objet, id_user, MIN(date) FROM historique ...
Qu'est-ce qui te garantit que le id_user qui est fourni est bien celui qui correspond à la date minimale ?
 
(réponse : rien :o  [:proy] )


heink ?
 
en toute logique, le id_user qui se trouve sur la même ligne que ta date, correspond forcément, car le id_user DOIT est dans le group by.
 
après, mysql permet de faire n'importe quoi, et se torche avec les 20000 pages de la norme SQL. c'est pas pour autant qu'il faut exploiter ses bugs et prendre pour acquis son comportement incohérent.

n°1621279
MagicBuzz
Posté le 09-10-2007 à 17:50:58  profilanswer
 

oublié mon poste d'avant le précédent.
à priori 100% à côté de la plaque.
 
l'hiver arrive, il est grand temps pour moi d'hiberner :o

n°1621346
mrbebert
Posté le 09-10-2007 à 21:36:36  profilanswer
 

MagicBuzz a écrit :


heink ?
 
en toute logique, le id_user qui se trouve sur la même ligne que ta date, correspond forcément, car le id_user DOIT est dans le group by.
 
après, mysql permet de faire n'importe quoi, et se torche avec les 20000 pages de la norme SQL. c'est pas pour autant qu'il faut exploiter ses bugs et prendre pour acquis son comportement incohérent.

Justement, il n'y est pas (et  n'a pas à y être dans ce cas).
Donc on est d'accord :o  


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [resolu]Besoin d'aide pour jointure sur mySQL

 

Sujets relatifs
[MySQL] pb avec une requête et EXISTS[Résolu] Tableau dynamique
[Resolu] Ie6 me surprendra toujours....[résolu] easy php
[C++] SetTimer...besoin d'aide.[RESOLU]creation fichier txt
[Resolu] Parcourir tout les fichier d'un dossier et detecter des mots[RESOLU] Trier sur deux tables
[Résolu]Modifier les style de lien pour une partie seulement 
Plus de sujets relatifs à : [resolu]Besoin d'aide pour jointure sur mySQL


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR