tags:

views:

72

answers:

2

I am making a cookie based favorite system and need to join data from two tables based on the unique user id stored in the cookie so I can tell what items that use has marked as favorites.

I know I need to do a JOIN but have not used them much and dont really have my head around them yet.

Existing query that selects the items from the db:

$query = mysql_query("SELECT *, UNIX_TIMESTAMP(`date`) AS `date` FROM songs WHERE date >= DATE_SUB( NOW( ) , INTERVAL 2 WEEK ) ORDER BY date DESC");

My favorites table is setup as: ID FAVORITE USERID where ID is the primary key, FAVORITE is the song ID from table songs and USERID is a hash stored in a cookie.

I need to join in all the rows from the favorites table where the USERID field matches the cookie hash variable.

I also need to gather the total number of rows in favorites that match the song id so I can display a count of the number of people who set the item as favorite so I can display how many people like it. But maybe need to do that as a separate query?

+1  A: 

This should do it, I would imagine:

$user_id = intval($_COOKIE['user_id']);
$query = mysql_query(sprintf("
    SELECT *
    FROM songs s
       INNER JOIN favorites f
       ON f.favorite = s.id
    WHERE f.userid = %s
", $user_id));

You should probably read up on the different types of joins.

And then to get the total amount of rows returned, you can just call mysql_num_rows on the result:

$favorite_song_count = mysql_num_rows($query);

EDIT: To select all songs but note which are favorited, you would do this:

$query = mysql_query(sprintf("
    SELECT s.*, f.id as favorite_id
    FROM songs s
       LEFT JOIN favorites f
       ON f.favorite = s.id AND f.userid = %s
", $user_id));

By switching it from an INNER JOIN to a LEFT JOIN we are selecting all songs even if they don't have a corresponding record in the favorites table. Any songs that are favorites of the user_id provided will have a non-NULL value for favorite_id.

Paolo Bergantino
This works but only returns the songs that match as favorites. I need to return all the songs but be able to note which are favorites and not by that particular user.
ian
LEFT JOIN still returns only 1 record... But I will play with it see if I can fix it.
ian
You're right, it wasn't the LEFT JOIN's fault but the where clause. It should be fixed now, I tested it.
Paolo Bergantino
Finally got it going! Thanks!
ian
I got the query going with some alterations: $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)); however it will now basically create a query that contains all favorites...So if i favorite a song in two browsers it will display the song twice... any ideas?
ian
add a GROUP BY s.id at the end
Paolo Bergantino
A: 

You can have logical (and, or, ...) operators in join conditions:

select t1.*
from t1
join t2 on t1.id = t2.fid and t2.foo = 'blah'

If you are also querying the total number of times each song has been "favorited" then you need a group by construct also, like this way:

select *, count(f.id)
from songs as s
left join favorites as f on s.id = f.favorite and f.userid = <hash>
group by s.id
azkotoki