Reputation: 3540
I have a php-page displaying a gallery. Under all items I print some info like good/bad votes (thumbs up/down) and the number of views it has.
For every inserted row in content there will also be a row inserted into content_views table. However the votes table will only contain rows if anyone has voted (1vote = 1row).
I want to select all info (content.*, views and votes if there is any) within a certain category (niche). The problem I have is that my query (see below) will return an empty result if there is no votes.
$result = mysql_query("
SELECT content.*, content_views.views as views, votes.good, votes.bad
FROM content, content_niches, content_views , votes
WHERE content_views.content = content.record_num
AND content.approved = 2
AND content_niches.content = content.record_num
AND votes.content = content.record_num
AND content_niches.niche = '$niche'
AND content.enabled = 1
GROUP BY content.record_num
ORDER BY $orderby DESC LIMIT $from,$max_results") or die(mysql_error());
Ofcourse I can do the following but since I have >50K rows in content and even more in votes this will be very slow.
$result = mysql_query("
SELECT content.*, content_views.views as views,
(SELECT votes.good FROM votes WHERE votes.content=content.record_num) AS good,
(SELECT votes.bad FROM votes WHERE votes.content=content.record_num) AS bad
FROM content, content_niches, content_views
WHERE content_views.content = content.record_num
AND content.approved = 2
AND content_niches.content = content.record_num
AND votes.video = content.record_num
AND content_niches.niche = '$niche'
AND content.enabled = 1
GROUP BY content.record_num
ORDER BY $orderby DESC LIMIT $from,$max_results") or die(mysql_error());
What is the “correct” way to do this?
Edit1: New query that is way too slow, what to do?
$result = mysql_query("
SELECT content.*,content_niches.*, content_views.views as views
FROM content
INNER JOIN
content_niches ON (content_niches.content = content.record_num AND content_niches.niche = '$chanid')
INNER JOIN
content_views ON (content_views.content = content.record_num )
LEFT OUTER JOIN votes
ON (votes.video = content.record_num)
WHERE content.approved = 2
AND content.enabled = 1
GROUP BY content.record_num
ORDER BY $orderby DESC LIMIT $from,$max_results") or die(mysql_error());
Upvotes: 0
Views: 258
Reputation: 23228
It's called an outer join
. A left outer join returns all rows from the left side and only those that match from the right side.
So, for example, if you have a post with 1 vote and a post with 0 votes, and you do this:
select *
from posts
left outer join votes
on posts.id = votes.id
It would return all of the posts and any of the votes records that exist and correspond.
You should really learn to use ansi-join syntax instead of non-ansi joins
Upvotes: 1