连接查询返回奇数结果

时间:2009-07-14 12:36:22

标签: php mysql

我使用此查询显示歌曲列表,并显示哪些歌曲被用户点击为收藏。

$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)
);

songs表设置为:id artist title duration等等。

favorites表设置为:id favorite userid

userid是存储在Cookie中的散列值,用于引用唯一用户。

查询工作正常,但出于某种原因我在一个浏览器中将歌曲标记为收藏。然后在另一个浏览器中将相同的歌曲标记为收藏,以模拟多个用户,歌曲将显示两次...每次标记为收藏夹一次,但最喜欢的指示符a< 3仍将正确显示。

有什么想法吗?

通过删除sprintf()很好地工作,但很想知道为什么这是有人有任何想法。

5 个答案:

答案 0 :(得分:1)

我有一个类似的问题,我认为如果你将And F.userid =%s更改为Where f.userid =%s它应该修复它吗?

答案 1 :(得分:1)

您正在使用sprintf和%s(字符串),但您没有将结果字符串值括在引号中。如果用户ID是字符串,则需要将其括在引号中,否则使用%d而不是%s。由于它在删除sprintf时工作正常,这似乎是问题所在。

答案 2 :(得分:0)

我认为你的ON - 条款是错误的。

试试这个:

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

答案 3 :(得分:0)

我相信以前的建议实际上会使LEFT JOIN失败,导致它充当INNER JOIN; f.userid有时为NULLNULL始终为false

我首先看一下favorites表的内容。如果我了解您的架构,您可能希望在favoritesfavoriteuserid上建立一个唯一键,以确保给定用户只能收听一首歌曲。也就是说,您可能会获得重复的行,因此会出现重复的结果。

答案 4 :(得分:0)

由于您使用的是“左连接”,我假设您想要所有歌曲的列表,并且您希望用户的收藏夹能够轻松区分。就像这样:

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

尝试以下方法:

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