2009-07-14 11 views
0

J'utilise cette requête pour afficher une liste de chansons et montrer quelles chansons ont été cliquées comme favoris par un utilisateur.rejoindre la requête en retournant des résultats impairs

$query = mysql_query(
    sprintf(" 
    SELECT 
     s.*, 
     UNIX_TIMESTAMP(`date`) AS `date`, 
     f.userid as favoritehash 
    FROM 
     songs s 
    LEFT JOIN 
     favorites f 
    ON 
     f.favorite = s.id 
     AND f.userid = %s", 
    $userhash) 
); 

Le tableau songs est configuré comme: id artist title duration etc., etc.

Le tableau favorites est configuré comme: id favorite userid

Le userid est une valeur de hachage stockée dans un cookie pour référencer un utilisateur unique .

La requête fonctionne correctement mais pour une raison quelconque, si je marque une chanson comme favorite dans un navigateur. Et puis marquer la même chanson que favori dans un autre navigateur pour simuler plusieurs utilisateurs, la chanson sera affichée deux fois ... une fois pour chaque fois qu'il est marqué favori, mais l'indicateur préféré un < 3 affichera toujours correctement.

Des idées?

Eh bien, il a fallu travailler via removign le sprintf() mais curieux de savoir pourquoi c'est si quelqu'un a des idées.

Répondre

1

Vous utilisez sprintf et% s (string), mais vous n'êtes pas Enfermer la valeur de chaîne résultante entre guillemets. Si l'ID utilisateur est une chaîne, vous devez l'encadrer entre guillemets, sinon utilisez% d au lieu de% s. Comme cela fonctionne bien lorsque vous supprimez sprintf, cela semble être le problème.

1

J'ai eu un problème similaire je pense que si vous changez le & F.userid =% s à Où f.userid =% s il devrait le réparer ?.

+0

J'ai effectivement enlevé toute la partie sprintf et il semble fonctionner parfaitement. – ian

0

Je crois que votre ON -clause est erroné.

essayer ceci:

ON f.favorite = s.id 
WHERE f.userid = %s 
+0

J'ai besoin d'être ET parce que je me suis assuré que l'élément favori correspond à la chanson en cours dans la rangée de la chanson ET l'utilisateur actif? – ian

+0

Eh bien, c'est ce que cela fait en ce qui me concerne – knittl

0

Je crois que les suggestions précédentes ne fait vaincre le LEFT JOIN, l'amenant à agir en tant INNER JOIN; f.userid serait parfois NULL, et NULL se compare toujours comme false.

Je commencerais par regarder le contenu de la table favorites. Si je comprends votre schéma, vous voudrez peut-être établir une clé unique sur favorites sur favorite et userid pour vous assurer qu'un utilisateur donné ne peut que préférer chaque chanson une fois. Autrement dit, vous pouvez obtenir des lignes en double, et donc des résultats en double.

+0

Eh bien, ce n'est pas des lignes en double parce que j'ai gardé un oeil sur le db comme je jouais avec elle. Une fois que j'ai enlevé le sprintf() cela a fonctionné parfaitement. Et les deux ID sur les deux tables sont la clé unique primaire. – ian

+0

C'est très étrange. Je suppose que vous l'avez remplacé par une concaténation de chaînes? La sortie de l'opération de chaîne était-elle visiblement différente après le changement? En outre, j'ai compris que vos colonnes 'id' étaient vos clés primaires, mais vous avez également une clé naturelle dans votre table de favoris, et vous pouvez vouloir la représenter avec une nouvelle clé unique. – WCWedin

0

Puisque vous utilisez une 'jointure à gauche', je suppose que vous voulez une liste de toutes les chansons et que vous voulez que les favoris des utilisateurs soient facilement reconnaissables. à-dire quelque chose comme ceci:

song1 details | date | null 
song2 details | date | userhash (favorite) 
song3 details | date | null 

les opérations suivantes:

SELECT s.*, UNIX_TIMESTAMP(`date`) AS `date`, f.userid as favoritehash 
FROM 
    songs s 
LEFT JOIN 
    (SELECT userid, favorite FROM favorites WHERE userid = %s) f 
ON 
    f.favorite = s.id 
Questions connexes