2009-07-14 7 views
0

Я использую этот запрос, чтобы отобразить список песен и показать, какие песни были нажаты как избранные пользователем.join query return odd results

$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 является значением хэшированного хранится в куки, чтобы ссылаться на уникального пользователя ,

Запрос работает нормально, но по какой-то причине, если я отмечаю песню как любимую в одном браузере. И затем отметьте ту же песню, что и фаворит в другом браузере, чтобы имитировать несколько пользователей, песня будет отображаться дважды ... один раз для каждого раза она отмечена как избранная, но любимый индикатор < 3 будет отображаться правильно.

Любые идеи?

Ну, это нужно для работы через смену sprintf(), но любопытно узнать, почему это происходит, если у кого есть идеи.

ответ

1

Вы используете Sprintf и% S (строка), но вы не заключаете результирующее значение строки в кавычках. Если идентификатор пользователя является строкой, вам необходимо заключить его в кавычки, иначе используйте% d вместо% s. Поскольку он отлично работает, когда вы удаляете sprintf, это может показаться проблемой.

1

У меня была аналогичная проблема, я думаю, если вы измените And F.userid =% s на Где f.userid =% s, это должно исправить ?.

+0

На самом деле я удалил всю часть sprintf и, похоже, работает идеально. – ian

0

Я думаю, что ваш ON -что неправильно.

попробуйте вместо этого:

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

Мне нужно, чтобы это было И потому что я понял, что любимый элемент соответствует текущей песне в строке песни И активному пользователю? – ian

+0

ну, вот что я делаю, насколько я знаю – knittl

0

Я считаю, что предыдущие предложения фактически победить LEFT JOIN, заставляя его действовать в качестве INNER JOIN; f.userid иногда будет NULL, а NULL всегда сравнивается с false.

Я бы начал с рассмотрения содержимого таблицы favorites. Если я понимаю вашу схему, вы можете установить уникальный ключ на favorites над favorite и userid, чтобы удостовериться, что данный пользователь может только любить каждую песню один раз. То есть вы можете получать повторяющиеся строки и, следовательно, дублировать результаты.

+0

Ну, это не повторяющиеся строки, потому что я смотрел на db, когда я играл с ним. Как только я удалил sprintf(), он работал отлично. И оба идентификатора на обеих таблицах являются основным уникальным ключом. – ian

+0

Это очень странно. Я предполагаю, что вы заменили его на конкатенацию строк? Был ли результат операции строки заметно отличаться после изменения? Кроме того, я понял, что ваши столбцы «id» были вашими первичными ключами, но у вас также есть естественный ключ в таблице избранных, и вы можете представить его с помощью нового уникального ключа. – WCWedin

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