Doublons indésirables

Doublons indésirables - SQL/NoSQL - Programmation

Marsh Posté le 26-10-2007 à 19:55:36    

Bonjour !
J'ai fait un ou l'autre Post qui n'ont recueilli aucun succès... surement trop long, trop vague, trop...
J'ai donc travaillé un peu sur tout ça et voilà quelque chose de plus concis !
 
Voici une requete MySQL que j'ai sur une page. Elle est créée à partir d'une boucle en PHP se basant sur des mots cles entres par l'user.
 
SELECT p.nom, p.dimension, p.couleur_id, mc.type FROM mot_cle mc LEFT JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle LEFT JOIN photos p ON ph_fk_mcl.id_photo = p.id WHERE (mc.fr = 'amour' OR mc.en = 'amour' OR mc.fr = 'homme' OR mc.en = 'homme' OR mc.fr = 'femme' OR mc.en = 'femme') AND (p.couleur_id = '1');
 
 
Cette requete sélectionne des photos dans une table.
 
Le problème : si une photo est associee à 2 mots cles, elle est deux fois dans les résultats ! Or, je voudrais plutot que la pertinence de cette photo soit plus élevée que celle d'une photo associée à un seul mot cle !
 
Est-ce que je dois trier un peu le tout via un tableau PHP ?
Est-ce qu'il y a moyen de faire ça dans la requete ?
 
Merci d'avance !!

Reply

Marsh Posté le 26-10-2007 à 19:55:36   

Reply

Marsh Posté le 26-10-2007 à 20:35:43    

SELECT p.nom, p.dimension, p.couleur_id, mc.type FROM mot_cle mc, COUNT(*)  
// la suite de ta requete  
GROUP BY p.nom, p.dimension, p.couleur_id, mc.type
ORDER BY COUNT(*) DESC

Reply

Marsh Posté le 27-10-2007 à 16:53:07    

Salut flo850 !  
Merci
 
Voici ma requete modifiee avec ton aide :
 
SELECT p.nom, p.dimension, p.couleur_id, mc.type FROM mot_cle mc, COUNT(*) LEFT JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle LEFT JOIN photos p ON ph_fk_mcl.id_photo = p.id WHERE (mc.fr = 'amour' OR mc.en = 'amour' OR mc.fr = 'ciel' OR mc.en = 'ciel' OR mc.fr = 'femme' OR mc.en = 'femme') GROUP BY p.nom, p.dimension, p.couleur_id, mc.type ORDER BY COUNT(*) DESC;
 
Mais j'obtient un message d'erreur... => Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource
 
Tu vois ce que ça pourrait être ?

Reply

Marsh Posté le 27-10-2007 à 16:57:10    

Après ton mysql_query(), fait un echo de mysql_error() ça t'en dira plus sur l'erreur.


Message édité par dwogsi le 27-10-2007 à 16:57:18

---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 27-10-2007 à 16:58:53    

oups
c'est pas SELECT p.nom, p.dimension, p.couleur_id, mc.type FROM mot_cle mc, COUNT(*)  
 
mais  
SELECT p.nom, p.dimension, p.couleur_id, mc.type, COUNT(*)  FROM mot_cle mc

Reply

Marsh Posté le 28-10-2007 à 11:51:51    

sorry...
j'ai essayé différent trucs... j'aurais franchement pu y penser !
J'essaye ça !
 
(Rem. : en fait la requete que j'ai affiche vient d'un echo en PHP)

Reply

Marsh Posté le 28-10-2007 à 11:54:12    

Voila mon echo de $query :
 
SELECT p.nom, p.dimension, p.couleur_id, mc.type, COUNT(*) FROM mot_cle mc LEFT JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle LEFT JOIN photos p ON ph_fk_mcl.id_photo = p.id WHERE (mc.fr = 'amour' OR mc.en = 'amour' OR mc.fr = 'ciel' OR mc.en = 'ciel' OR mc.fr = 'enfant' OR mc.en = 'enfant') GROUP BY p.nom, p.dimension, p.couleur_id, mc.type ORDER BY COUNT(*) DESC  
 
Y'a toujours une erreur dans la requete...
Je vais un peu regardé mais si tu as une idée... !!

Reply

Marsh Posté le 28-10-2007 à 11:56:41    

mysql_error() => Utilisation invalide de la clause GROUP
 
En fait je me demandais pourquoi il fallait mettre les 4 dans la clause GROUP... ??

Reply

Marsh Posté le 28-10-2007 à 12:25:07    

il faut mettre dans la clause group toutes les colonnes qui ne sont pas dans des fonctions d'agregation ( min,max, count ,... )
 
par contre, je vois pas pour l'erreur

Reply

Marsh Posté le 28-10-2007 à 12:39:29    

Ben moi non plus !
 
j'ai toujours la même erreur :  
 
Requete :  
SELECT p.nom, p.dimension, p.couleur_id, mc.type, COUNT(*)  
FROM mot_cle mc  
LEFT JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle  
LEFT JOIN photos p ON ph_fk_mcl.id_photo = p.id WHERE (mc.fr = 'amour' OR mc.en = 'amour' OR mc.fr = 'ciel' OR mc.en = 'ciel' OR mc.fr = 'enfant' OR mc.en = 'enfant') AND (p.couleur_id = '2')  
GROUP BY p.nom, p.dimension, p.couleur_id, mc.type  
ORDER BY COUNT(*) DESC
 
 
Erreur : Utilisation invalide de la clause GROUP

Reply

Marsh Posté le 28-10-2007 à 12:39:29   

Reply

Marsh Posté le 28-10-2007 à 13:03:34    

tu peux essayer en ne mettant que p.nom dans la liste des champs et des group ?

Reply

Marsh Posté le 28-10-2007 à 13:05:36    

Voili...
 
Requete : SELECT p.nom, COUNT(*) FROM mot_cle mc LEFT JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle LEFT JOIN photos p ON ph_fk_mcl.id_photo = p.id WHERE (mc.fr = 'amour' OR mc.en = 'amour' OR mc.fr = 'ciel' OR mc.en = 'ciel' OR mc.fr = 'enfant' OR mc.en = 'enfant') AND (p.couleur_id = '2') GROUP BY p.nom ORDER BY COUNT(*) DESC
 
 
Erreur : Utilisation invalide de la clause GROUP

Reply

Marsh Posté le 28-10-2007 à 13:21:46    

avec ça, je n'ai plus d'erreur...
mais ça ne supprime pas les doublons...
et ce n'est pas trié par perinence...
 
SELECT p.nom, p.dimension, p.couleur_id, mc.type, COUNT(*)  
FROM mot_cle mc  
LEFT JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle  
LEFT JOIN photos p ON ph_fk_mcl.id_photo = p.id  
WHERE (mc.fr = 'amour' OR mc.en = 'amour' OR mc.fr = 'mer' OR mc.en = 'mer' OR mc.fr = 'amitie' OR mc.en = 'amitie' OR mc.fr = 'ciel' OR mc.en = 'ciel' OR mc.fr = 'enfant' OR mc.en = 'enfant' OR mc.fr = 'homme' OR mc.en = 'homme' OR mc.fr = 'femme' OR mc.en = 'femme')  
GROUP BY p.nom, p.dimension, p.couleur_id, mc.type  
ORDER BY p.nom
 
Affichage des résultats :  
 
nom photo = 1.jpg | dim. = 124x156 | coul. = 1 | type de mot = mot-cle
nom photo = 10.jpg | dim. = 156x354 | coul. = 1 | type de mot = concept
nom photo = 10.jpg | dim. = 156x354 | coul. = 1 | type de mot = mot-cle
nom photo = 11.jpg | dim. = 145x652 | coul. = 1 | type de mot = mot-cle
nom photo = 12.jpg | dim. = 600x800 | coul. = 2 | type de mot = mot-cle
nom photo = 13.jpg | dim. = 745x254 | coul. = 1 | type de mot = mot-cle
nom photo = 14.jpg | dim. = 123x154 | coul. = 1 | type de mot = mot-cle
nom photo = 15.jpg | dim. = 143x213 | coul. = 1 | type de mot = mot-cle
nom photo = 17.jpg | dim. = 159x157 | coul. = 1 | type de mot = mot-cle
nom photo = 19.jpg | dim. = 3101x785 | coul. = 1 | type de mot = mot-cle
nom photo = 3.jpg | dim. = 258x369 | coul. = 1 | type de mot = mot-cle
nom photo = 5.jpg | dim. = 159x159 | coul. = 1 | type de mot = mot-cle
nom photo = 7.jpg | dim. = 148x358 | coul. = 2 | type de mot = mot-cle
nom photo = 8.jpg | dim. = 148x159 | coul. = 2 | type de mot = mot-cle
nom photo = 9.jpg | dim. = 354x354 | coul. = 1 | type de mot = concept
nom photo = 9.jpg | dim. = 354x354 | coul. = 1 | type de mot = mot-cle

Reply

Marsh Posté le 28-10-2007 à 13:25:00    

Visiblement quand on utilise COUNT(*) dans la clause GROUP ça fait une erreur dans la clause GROUP !?!

Reply

Marsh Posté le 28-10-2007 à 14:01:36    

Sorry....
Visiblement quand on utilise COUNT(*) dans la clause ORDER ça fait une erreur dans la clause GROUP !?!

Reply

Marsh Posté le 29-10-2007 à 14:05:00    

dans la clause order, utilise l'alias de ton count :
 

Code :
  1. SELECT count(*) nb, truc
  2. FROM machin
  3. GROUP BY truc
  4. ORDER BY nb

Reply

Marsh Posté le 29-10-2007 à 17:40:01    

Je vérifie tout de même... MAIS ca a l'air de bien marcher !!!!!

Reply

Marsh Posté le 29-10-2007 à 17:53:24    

Un rand merci à flo850 et MagicBuzz!!
 
Voici à quoi ressemble ma requete maintenant.
Et, elle semble bien fonctionner !!
 
SELECT p.nom, p.dimension, p.couleur_id, mc.type, COUNT(*) co FROM mot_cle mc LEFT JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle LEFT JOIN photos p ON ph_fk_mcl.id_photo = p.id WHERE (mc.fr = 'homme' OR mc.en = 'homme' OR mc.fr = 'femme' OR mc.en = 'femme' OR mc.fr = 'enfant' OR mc.en = 'enfant' OR mc.fr = 'ciel' OR mc.en = 'ciel') AND (p.couleur_id = '2') GROUP BY p.nom, p.dimension, p.couleur_id, mc.type ORDER BY co
 
Quelqu'un pourrait-il me dire si elle semble optimale ?
Si il a encore moyen de l'améliorer ?

Reply

Marsh Posté le 30-10-2007 à 09:40:37    

mise à part les LEFT OUTER JOIN qui sont loin d'être optimum et qui méritent vérification de leur réelle utilité, il n'y a pas de problème avec ta requête. Tu peux quand même rajouter tes "OR" par des "IN", ça devrait être un peu plus clair.
 
PS : C'est quoi l'éditeur de merde que tu utilises et qui te fait des "LEFT JOIN" sans le mot-clé "OUTER" (qui est le mot le plus important). Ou si tu n'utilises pas un GUI, quel bouquin tu utilises ? Quel éditeur ? Que j'aille poser une bombe chez eux.
 
Ca me fait bondir tous les 4 matins de voir des notations de jointures attrophiées au profit d'une illisibilité exemplaire :sweat:

Reply

Marsh Posté le 30-10-2007 à 10:08:48    

MagicBuzz a écrit :

mise à part les LEFT OUTER JOIN qui sont loin d'être optimum et qui méritent vérification de leur réelle utilité,


Ils sont inutiles et transformés en inner par les conditions dans le where ;)

MagicBuzz a écrit :


il n'y a pas de problème avec ta requête. Tu peux quand même rajouter tes "OR" par des "IN", ça devrait être un peu plus clair.


Tout à fait, et j'aurais même tendance à "inverser" le sens du IN pour que cela soit limpide, genre!

Code :
  1. ...WHERE 'homme' IN (mc.fr, mc.en) OR  ...


Mais honnêtement, si tu veux optimiser "à fond" la requete je créerais une table temporaire avec les listes des valeurs et je jointerais dessus (ci dessous en syntaxe db2 à adapter en fonction du sgbd)

Code :
  1. SELECT
  2. p.nom,
  3. p.dimension,
  4. p.couleur_id,
  5. mc.type,
  6. COUNT(*) co
  7. FROM
  8.                  mot_cle mc
  9. INNER JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle
  10. INNER JOIN photos p ON ph_fk_mcl.id_photo = p.id  AND p.couleur_id=2
  11. INNER JOIN TABLE(VALUES('femme', 'homme', 'ciel')) AS t(KEY) ON mc.en=t.KEY OR mc.fr=t.KEY
  12. GROUP BY
  13. p.nom,
  14. p.dimension,
  15. p.couleur_id,
  16. mc.type
  17. ORDER BY co
 


Message édité par anapajari le 30-10-2007 à 10:09:14
Reply

Marsh Posté le 30-10-2007 à 10:35:19    


Je n'utilise pas d'éditeur MagicBuzz... Et comme je remets à MySQL après longtemps... je n'ai plus trop la méthode... Je vais chercher des infos par-ci, par-là et j'avance petit à petit... Il faut que je m'y remette une bonne fois !!!
Donc la bombe c'est chez moi qu'il va falloir la mettre !   :D  
 
Je pense que je vais essayer avec le IN comme ça je peux encore laisser le choix à l'user de choisir que tous les mots soient pris en compte (AND) ou au mopins un des mots (OR) !
 
...WHERE 'homme' IN (mc.fr, mc.en) AND  ...
...WHERE 'homme' IN (mc.fr, mc.en) OR  ...
 
Un grand merci !
J'avance bien sur mon projet grâce à vous !
 
(°-°)

Reply

Marsh Posté le 30-10-2007 à 10:48:08    


Pourriez-vous me dire ce que vous pensez de l'utilisation de LIKE dans ma requete ?
 
Ca me permettrait de pouvoir utiliser _ et % pour rendre ma recherche plus sensible :
 
- %jardin% => prendra en compte "jardinier"
- _v_nement => "événement" remplacer les caractères accentués (et créer ma table Mot_cle en fonction)
- ...
 
(°-°)

Reply

Marsh Posté le 30-10-2007 à 10:54:13    

Euh...
 
LIKE, oublie.
 
C'est vraiment un tueur de perfs, pour un résultat... Extrêment limité !
 
Recherche du côté des "TEXT INDEX" et autres (y'a pas deux SGBD qui les appelle pareil).
 
Ca permet d'utiliser des fonctions telles que "MATCH", "CONTAINS", "FREETEXT", etc. qui sont bien plus performantes (ça permet de faire des recherches plus naturelles, basées sur un véritable dictionnaire linguistique -donc selon les SGBD on peut même faire des requêtes sur "baker" et récupérer les lignes qui parlent de "croissants" ;)-)

Reply

Marsh Posté le 30-10-2007 à 13:08:09    

Ok, merci !
Je vais plancher un peu la dessus !
(°-°)

Reply

Marsh Posté le 30-10-2007 à 17:08:15    

J'utilise PHP/MySQL et ce qu'on peut faire c'est des recherches en texte intégral. Mais il pratiquement pas d'options.
 
- On peut rechercher en mode booléens (ça m'intéresse moyen)
- On peut utiliser l'extension de requete aveugle (dans mon cas si je rentre des mots clés légèrement différent, p.ex. "homme femm" ou "homme femmes" à la place de "homme femme", le résultat est le même que si je n'avais mis que "homme" )
 
Ca ne laisse donc pas trop de "liberté d'erreurs" à l'utilisateur !

Reply

Marsh Posté le 30-10-2007 à 17:18:59    

port'nawak [:dawak]
tu n'as pas du bien lire la doc: http://dev.mysql.com/doc/refman/5. [...] olean.html
Après c'est à toi de correctement formater ta chaine de recherche en fonction de  ce que l'utilisateur a rentré!

Reply

Marsh Posté le 30-10-2007 à 17:30:16    

Bon... là je crois qu'il est temps que je travaille un peu tout ça avant de revenir avec des bêtes questions !!!
(°-°)

Reply

Marsh Posté le 31-10-2007 à 13:47:01    

Je crois que je vais en rester là pour le moment avec ma requete !
Je la ferai évoluer plus tard.
 
Des commentaires sur cetteversion de ma requete ?
 
SELECT p.nom, p.dimension, p.couleur_id, mc.type, COUNT(*) co  
FROM mot_cle mc  
INNER JOIN ph_fk_mcl ON mc.id = ph_fk_mcl.id_motcle  
INNER JOIN photos p ON ph_fk_mcl.id_photo = p.id  
WHERE (MATCH (mc.fr, mc.en) AGAINST ('homme* femme* enfant*' IN BOOLEAN MODE)) AND (p.couleur_id = '1')  
GROUP BY p.nom, p.dimension, p.couleur_id, mc.type  
ORDER BY co DESC
 
(°-°)

Reply

Marsh Posté le 31-10-2007 à 14:33:14    

Heu, je vais peut-être dire une connerie, mais un DISTINCT, ce serait pas mieux qu'un GROUP BY ?
 
Là, on a pas besoin d'un regroupement ! Tout ce qu'on veut, c'est que les enregistrements soit distincts !


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
Reply

Marsh Posté le 31-10-2007 à 14:44:01    

bah il fait un count() donc non, le group by n'est pas idiot

Reply

Marsh Posté le 31-10-2007 à 14:50:53    

Ha mince ! J'avais zappé le fait qu'il voulait un tri par pertinence !
Donc effectivement, le GROUP BY n'est pas de trop ! :P


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
Reply

Marsh Posté le 31-10-2007 à 19:41:02    

Encore une petite question...
 
Est-ce que avec MySQL il y a moyen de rechercher des mots semblables phonétiquement, orthographiquement, ... ?
 
J'ai vu la distance levenstein en PHP mais je ne vois pas bien comment l'intégrer dans ma requete...
 
(°-°)

Reply

Marsh Posté le 31-10-2007 à 20:01:44    

regarde du côté de soundex() si ça existe

Reply

Marsh Posté le 31-10-2007 à 20:37:38    

Extra ! On dirait bien que ça existe en MySQL !
Il y a aussi SOUNDS LIKE... Je vais voir tout ça...
Je pensais que ce n'était qu'une fonction PHP !
Merci à toi !!!
(°-°)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed