Reputation: 1
I have dynamic conditions. Sometimes there are conditions and sometimes not. I want to get all results from the left but exclude rows that do not match conditions. Is there any way I can achieve this? With what I have it always gets all rows from the left. If I use inner join it won't get the records from the base table if they can't join. I need to be able to get all records from the anime table, however if there is a condition set, then only get the records that match the conditions.
SELECT anime.id, anime.title, IF(english IS NULL or english = '', anime.title, english) as english, anime.slug
FROM anime
LEFT JOIN genres g ON g.anime_id = anime.id
LEFT JOIN episodes e ON e.anime_id = anime.id
LEFT JOIN videos v on v.episode_id = e.id
$conds
GROUP BY anime.id
ORDER BY $order
LIMIT $limit
$conds, $order, and $limit is the dynamically generated with php.
an example for a condition is
WHERE anime.status = 'completed' AND v.type = 'subbed'
The problem here is if I use left join the condition for v.type is completely ignored and it gets all records from the anime table.
Doing a left join will get all rows from the anime table regardless. But I want to not get all rows if there is a condition and only the rows that match the condition. But if there is no conditions then get all rows anyways.
If I use INNER JOIN instead of LEFT JOIN, if an anime has no episodes or videos it won't get them, but I NEED to get them.
Upvotes: 0
Views: 1978
Reputation: 11
I had a similar trouble, you need to use EXISTS, as the following example:
SELECT t1.* FROM table_1 t1
WHERE EXISTS (SELECT t2.* FROM table2 t2
WHERE t1.id=t2.t1_id AND t2.some_field='some value')
So your query should look like this:
SELECT anime.id, anime.title, IF(english IS NULL or english = '', anime.title, english) as english, anime.slug
FROM anime
LEFT JOIN genres g ON g.anime_id = anime.id
LEFT JOIN episodes e ON e.anime_id = anime.id
WHERE EXISTS (SELECT v.* FROM videos v WHERE v.episode_id = e.id AND v.type = 'subbed')
AND anime.status = 'completed'
GROUP BY anime.id
ORDER BY $order
LIMIT $limit
i know that your question is old, but i submit this for anyone with a similar problem :)
Upvotes: 1
Reputation: 3906
Maybe you need the following
$query_with_condition = "SELECT ...
FROM anime
LEFT JOIN genres g ON g.anime_id = anime.id
LEFT JOIN episodes e ON e.anime_id = anime.id
LEFT JOIN videos v on v.episode_id = e.id
$conds
GROUP BY anime.id
ORDER BY $order
LIMIT $limit";
$query_without_condition = "SELECT ...
FROM anime
LEFT JOIN genres g ON g.anime_id = anime.id
LEFT JOIN episodes e ON e.anime_id = anime.id
LEFT JOIN videos v on v.episode_id = e.id
GROUP BY anime.id
ORDER BY $order
LIMIT $limit";
$result = mysql_query($query_with_condition, $conn);
$num_rows = mysql_num_rows($result);
// if the query with conditions doesn't return any rows
if(!$num_rows){
// then we use the second query where no conditions
$result = mysql_query($query_without_condition, $conn);
}
// use $result
I don't know but maybe you need the following
WHERE anime.status = 'completed' AND IFNULL(v.type,'subbed') = 'subbed'
It also returns row from the left-table if this row haven't link with a video.
If I'm mistaken please, add test data for tables anime
and videos
.
And show an expected result for this data.
Upvotes: 0
Reputation: 35613
The "generic answer" is if you want the left join to "survive" a where clause condition you must also allow for NULL to be returned by the left join.
WHERE anime.status = 'completed' AND (v.type = 'subbed' OR v.type IS NULL)
nb: If you use functions to mimic the same effect then you removed access to indexes and that may badly affect query performance.
Upvotes: 0