[résolu] jointure et 'distinct'

WRInaute impliqué
Bonjour à tous,
J'ai un petit problème avec une requête qui doit me retourner les fiches qui ont été commentées en dernier.
La requete fonctionne bien sauf que si une fiche a reçu plusieurs commentaires récemment, elle resortira plusieurs fois dans ma liste, ce que je ne souhaite pas.

Code:
SELECT Fiche.*, Comment.created_at AS last_comment_created_at 
FROM dkannu_fiches Fiche 
JOIN dkannu_comments Comment ON Fiche.id=Comment.fiche_id AND Comment.online=1 
WHERE Fiche.online='1' 
ORDER BY Comment.created_at DESC 
LIMIT 20

J'ai essayé d'utiliser DISTINCT et GROUP BY mais les résultats ne sont pas ceux attendus, une bonne âme pourra-t-elle m'aider ?

J'avoue que je suis à cours d'idée là :?
 
WRInaute discret
Tu devrais pouvoir faire une sous requete
-http://dev.mysql.com/doc/refman/5.1/en/subqueries.html
 
WRInaute passionné
Dans le cas présent je verrais plutôt un "group by". Tout ce qui t'intéresse dans "kannu_comments" c'est la date de création la plus récente.
 
WRInaute impliqué
Merci à tous les 2 d'avoir répondus :D

Pouvez-vous (si possible) me donner un exemple de requete car je ne vois pas comment faire avec la sous-requete.
J'ai aussi essayé le GROUP BY mais ca ne prenait pas forcément le dernier commentaire d'une fiche (j'ai probablement du mal m'y prendre)
 
WRInaute accro
Salut, voila 2 requêtes. Je me suis construit une tite table fiche et commentaire et voila ce qui en ressort:

Code:
select fiche.id as idfiche, comment.date, comment.id as idcomm
from comment inner join fiche on (comment.id_fiche = fiche.id)
group by comment.id_fiche
order by comment.date DESC

ou encore, une plus farfelue moins consommatrice de mémoire mais surement plus lente:

Code:
select id as idcomm,date,(select id from fiche where id = (select id_fiche from comment where id = idcomm)) as idfiche
from comment
group by id_fiche
order by date DESC
 
WRInaute impliqué
Génial, je vais tester ça demain à la première heure, certainement la première requete car comme je suis en mutualisé je me tamponne de la consommation mémoire (joke ;))

Si ca marche, je te remercierai 1000 fois (et bool/lupuz aussi bien entendu) , sinon je me mettrai à la broderie :p
 
WRInaute passionné
sans un max() pour récupérer la date la plus récente, tu vas surtout avoir des résultats aléatoires ;)
 
WRInaute impliqué
Bool a dit:
sans un max() pour récupérer la date la plus récente, tu vas surtout avoir des résultats aléatoires ;)
Arf, des résultats aléatoire, j'en ai eu pas mal en testant diverses requetes :?

Que recommandes-tu ? ou placerais-tu le MAX() ?

Encore merci de m'aider :D
 
WRInaute discret
Re: [sql] jointure et 'distinct'

seebz a dit:
Bonjour à tous,
J'ai un petit problème avec une requête qui doit me retourner les fiches qui ont été commentées en dernier.
La requete fonctionne bien sauf que si une fiche a reçu plusieurs commentaires récemment, elle resortira plusieurs fois dans ma liste, ce que je ne souhaite pas.

Code:
SELECT Fiche.*, Comment.created_at AS last_comment_created_at 
FROM dkannu_fiches Fiche 
JOIN dkannu_comments Comment ON Fiche.id=Comment.fiche_id AND Comment.online=1 
WHERE Fiche.online='1' 
ORDER BY Comment.created_at DESC 
LIMIT 20

J'ai essayé d'utiliser DISTINCT et GROUP BY mais les résultats ne sont pas ceux attendus, une bonne âme pourra-t-elle m'aider ?

J'avoue que je suis à cours d'idée là :?

déjà je pense que la requete à un problème dans la jointure et que le Comment.online=1 doit se trouver apres la première close where :

Code:
SELECT Fiche.*, Comment.created_at AS last_comment_created_at 
FROM dkannu_fiches Fiche 
JOIN dkannu_comments Comment ON Fiche.id=Comment.fiche_id
WHERE Fiche.online='1'  AND Comment.online='1' 
ORDER BY Comment.created_at DESC 
LIMIT 20

Ensuite je mettrai un group by Fiche.id (ou ref ou num je sais pas quel est l'identifiant de tes fiche) pour éviter les doublons donc un truc final comme ça :

Code:
SELECT Fiche.*, Comment.created_at AS last_comment_created_at 
FROM dkannu_fiches Fiche 
JOIN dkannu_comments Comment ON Fiche.id=Comment.fiche_id
WHERE Fiche.online='1'  AND Comment.online='1'
GROUP BY Fiche.id 
ORDER BY Comment.created_at DESC
LIMIT 20
 
WRInaute passionné
De manière générale si vous avez un GROUP BY sans le moindre appel à une fonction d'agrégation (min(), max(), avg(), count(), etc), c'est qu'il y a un pépin dans votre requête...
 
WRInaute accro
Youps, merci bool, heureusement que tu suis :D J'ai été légèrement vite, voila la requête corrigé avec le MAX(date) et pas date :D

Code:
SELECT fiche.id as idfiche,max(date) as last,comment.id as idcom
FROM comment INNER JOIN fiche ON (fiche.id = comment.id_fiche)
GROUP by id_fiche
ORDER BY last DESC

Et les résultats du test, beaucoup plus pertinents :p


Table commentaire
Code:
Textes complets  	id 	date 	id_fiche
	Modifier 	Effacer 	1 	2009-01-06 23:59:39 	1
	Modifier 	Effacer 	2 	2009-01-06 23:48:02 	3
	Modifier 	Effacer 	3 	2009-01-06 23:48:07 	4
	Modifier 	Effacer 	4 	2009-01-06 23:42:21 	2
	Modifier 	Effacer 	5 	2009-01-06 23:53:21 	3
	Modifier 	Effacer 	6 	2009-01-06 23:48:30 	1
	Modifier 	Effacer 	7 	2009-01-06 23:48:12 	2

Table Fiche

Code:
Textes complets  	id
	Modifier 	Effacer 	1
	Modifier 	Effacer 	2
	Modifier 	Effacer 	3
	Modifier 	Effacer 	4

Résultat de la requête:

Code:
idfiche 	last Décroissant 	idcom
1 	2009-01-06 23:59:39 	1
3 	2009-01-06 23:53:21 	2
2 	2009-01-06 23:48:12 	4
4 	2009-01-06 23:48:07 	3
 
WRInaute impliqué
Je vois que certains ont bossés tard sur mon problème et je les remercie ;)

Je viens de tester et le gagnant est [..roulement de tambours..] YoyoS (avec les remarques de Bool et coolspot).
La requete finale est la suivante :
Code:
SELECT Fiche.*, MAX(Comment.created_at) AS last_comment_created_at 
FROM dkannu_fiches Fiche 
INNER JOIN dkannu_comments Comment 
	ON Fiche.id=Comment.fiche_id 
WHERE Fiche.online='1' AND Comment.online='1' 
GROUP BY Comment.fiche_id 
ORDER BY last_comment_created_at DESC 
LIMIT 20

Je suis content que ca fonctionne, ca m'évitera d'apprendre la broderie :p
Comme promis :
Code:
$thanks_to = array('YoyoS', 'Bool', 'coolspot', 'lupuz');
for($i=0; $i<1000; $i++) 
	printf('Merci à %s et longue vie à WRI !<br />', join(', ', $thanks_to));
 
WRInaute accro
T'aurais pu nous faire une page php dédiée qu'on puisse executer avec la boucle des remerciements quand même :D
 
Discussions similaires
Haut