Mysql join not getting proper values - mysql

I have 3 tables
movies_detais
movies_revies
movies_gossips
What I want is that I want all the data whose movies_relesed_type=0 and movies_type=1
But I am not getting desired values
Code
Select md.movies_name,
md.movies_description,
mr.rt_user_comments,
mg.gossip_desc
from movies_details md
Inner join movies_reviews mr
on md.movies_id=mr.movie_review_id
Inner join movies_gossips mg
on md.movies_id=mg.movies_gossip_id
and md.movie_relesed_type='0'
and md.movie_type='1'
With this code I am only getting one row whose movies_relesed_type=0 and movies_type=1, but in my table I am having other rows also which meets the condition but they are not displaying.

I think this is a case where you want the conditions in the where clause:
Select md.movies_name,
md.movies_description,
mr.rt_user_comments,
mg.gossip_desc
from movies_details md Inner join
movies_reviews mr
on md.movies_id=mr.movie_review_id left join
movies_gossips mg
on md.movies_id = mg.movies_gossip_id
where md.movie_relesed_type='0' and md.movie_type = '1';
A left outer join returns all the rows from the first table, even when the condition in the on clause evaluates to not-true. This is true regardless of which table the conditions refer to. So, you cannot filter on the first table in the on clause using a left outer join.

Related

WHERE followed by ON clause

What is the semantic difference between the following queries? To me both seemed similar until I executed them on presto. Is this something specific to presto or am I missing something in the SQL standard?
Form 1: All conditions specified in the ON clause.
SELECT
t1.colA,
t1.colB,
t1.colC,
t2.colD
FROM t1
LEFT OUTER JOIN t2
ON t1.colA = t2.colA
AND t1.colB = t2.colB
AND t1.colE = 1
AND t2.colF = 2;
Form 2: Some conditions specified in the WHERE clause instead.
SELECT
t1.colA,
t1.colB,
t1.colC,
t2.colD
FROM t1
LEFT OUTER JOIN t2
ON t1.colA = t2.colA
AND t1.colB = t2.colB
WHERE
t1.colE = 1
AND t2.colF = 2;
Form 1 results in some rows but form 2 doesn't but shouldn't they be equivalent?
There are two important differences.
First the condition t1.colE = 1. A LEFT JOIN keeps all rows in the first table, regardless of what the ON clause evaluates to. So, t1.colE does not change the number of rows in the result set. However, it does have the strange effect that any columns from t2 when this condition is not true are NULL.
Second the condition t2.colF = 2 has a different effect. This turns the LEFT JOIN into an INNER JOIN, because NULL values do not match the WHERE clause.
When you have a LEFT [OUTER] JOIN and WHERE clause that references the right_table, it is equivalent to an [INNER] JOIN. That is, the following two are equivalent:
-- [inner] join
select ...
from left_table
join right_table
on left_table.cola = right_table.cola
and right_table.colb = 2
-- left [outer] join + where
select ...
from left_table
left join right_table
on left_table.cola = right_table.cola
where right_table.colb = 2
Your 2nd example query has a left join and this condition t2.colF = 2 in the where clause, making it different from the first query.
where the the first includes all rows from t1, the second includes only rows where t1.colE = 1 and t2.colF = 2
The way to think about the difference between the WHERE clause and the ON clause is:
The WHERE clause determines which of the rows produced by the FROM clause should be considered in the query, so it's role is to filter rows before they get processed by a GROUP BY, WINDOW or the SELECT clause.
The ON clause determines whether a pair of rows from the left and right side of a JOIN should be considered for the join operation.
For an INNER JOIN, if the ON clause evaluates to false, the rows are not joined with each other and no result is emitted.
For a LEFT JOIN, if, for a given row on the left side the ON clause evaluates to false for all rows on the right side, a row containing the values from the left side and NULLs for the columns on the right side is emitted. The same logic applies for a RIGHT JOIN, but with the sides reversed.
A FULL JOIN is a combination of LEFT and RIGHT joins.
In your example, the second query, any row produced by the LEFT JOIN that contains NULLs in columns from the right side due to the ON clause evaluating to false will be filtered out by the t2.colF = 2 expression WHERE clause.

How can I populate a table when inner join values might be null?

I'm populating a table which is fetching the ids from 2 other tables to display their information, for example, delivery has a Hamburguer and the box, but the user might register the delivery with out the box, only with the hamburguer.
When I make a INNER JOIN SELECT to get the data from the DB it will return 0 results since there is no box and I'm trying to compare the ids that don't exist. It doesn't populate the table then.
SELECT
entrega_telemovel.*,
telemovel.id_telemovel,
telemovel.nroserie,
nro_telemovel.numero_telemovel,
nro_telemovel.id_nrotelemovel,
funcionarios.id_funcionario,
funcionarios.nome
FROM entrega_telemovel
INNER JOIN telemovel
ON entrega_telemovel.telemovel = telemovel.id_telemovel
INNER JOIN nro_telemovel
ON nro_telemovel.id_nrotelemovel = entrega_telemovel.numero_telemovel
INNER JOIN funcionarios
ON funcionarios.id_funcionario = entrega_telemovel.funcionario_entrega
ORDER BY funcionarios.nome;
In this query above entrega_telemovel.telemovel=telemovel.id_telemovel the value in entrega_telemovel.telemovel is null like the example I gave above. So 0 results are returned from the query.
How can I solve this ?
You are looking for a LEFT JOIN.
INNER JOIN only combines rows, that exist in both tables. A LEFT JOIN on the other hand always produces at least one row. If on table does not have a match for it, all columns are set to NULL.
SELECT
entrega_telemovel.*,
telemovel.id_telemovel,
telemovel.nroserie,
nro_telemovel.numero_telemovel,
nro_telemovel.id_nrotelemovel,
funcionarios.id_funcionario,
funcionarios.nome
FROM entrega_telemovel
LEFT JOIN telemovel
ON entrega_telemovel.telemovel = telemovel.id_telemovel
LEFT JOIN nro_telemovel
ON nro_telemovel.id_nrotelemovel = entrega_telemovel.numero_telemovel
LEFT JOIN funcionarios
ON funcionarios.id_funcionario = entrega_telemovel.funcionario_entrega
ORDER BY funcionarios.nome;
You want to show all entrega_telemovel entries, no matter whether they have a match in entrega_telemovel or not. This is what an outer join does.
SELECT ...
FROM entrega_telemovel et
LEFT OUTER JOIN telemovel t ON et.telemovel = t.id_telemovel
...

MySQL - How to get one of the repeated records given a condition in SQL?

I have the next results from a query. I did this:
Where the user "Adriana Smith" with ID 6 is repeated because she has different contract dates, to do that I did a left join from table bo_users to bo_users_contracts (1:m One to Many Relation). The query is below:
SELECT bo_users.ID, bo_users.display_name, COALESCE (bo_users_contracts.contract_start_date,'-') AS contract_start_date, COALESCE (bo_users_contracts.contract_end_date, '-') AS contract_end_date, COALESCE (bo_users_contracts.current,'-') AS current
FROM bo_users
LEFT JOIN bo_users_contracts ON bo_users.ID = bo_users_contracts.bo_users_id
LEFT JOIN bo_usermeta ON bo_users.ID = bo_usermeta.user_id
WHERE (bo_usermeta.meta_key = 'role' AND bo_usermeta.meta_value = 'member')
But I want to get all users, but from user Adriana I just want to get the occurrence where "current" column = 1.
So the final result would be the 3 user's records:
Alejandro, Rhonda and Adriana (with "current" = 1)
Thank you!
Since you want to limit on a table being outer joined, the limit should be placed on the join itself so the all records from bo_users is retained. (as indicated desired by the outer join)
Essentially the limit is applied before the join so the unmatched records from BO_users to bo_users_contracts are kept. If applied after the join in a where clause the records from BO_user without a matching record would have a null value for current and thus be excluded when the current=1 filter is applied.
In this example the only values which should be in the where would be from table BO_USERS.
I'd even move the bo_usermeta filters to the join or you may lose bo_users; or the left join on the 3rd table should be an inner join.
SELECT bo_users.ID
, bo_users.display_name
, COALESCE (bo_users_contracts.contract_start_date,'-') AS contract_start_date
, COALESCE (bo_users_contracts.contract_end_date, '-') AS contract_end_date
, COALESCE (bo_users_contracts.current,'-') AS current
FROM bo_users
LEFT JOIN bo_users_contracts
ON bo_users.ID = bo_users_contracts.bo_users_id
and bo_users_contracts.current = 1
LEFT JOIN bo_usermeta --This is suspect
ON bo_users.ID = bo_usermeta.user_id
WHERE (bo_usermeta.meta_key = 'role' --this is suspect
AND bo_usermeta.meta_value = 'member') --this is suspect
The lines reading this is suspect are that way because you have a left join which means you want all users from bo_users.. However if a user doesn't have a meta_key or meta_value defined, they would be eliminated. Either change the join to an inner join or move the where clause limits to the join. I indicate this as you're query is "inconsistent" in it's definition leading to ambiguity when later maintained.

mysql right join not working as expected

When I use right join I get the same results as using left join or just join. Can anyone show me where I have gone wrong?
I have 3 tables as follows:
langugages
id
code eg "hu","en"
language_default
id
text
language_translations
id
lang_id (FK the id of the language in the languages table)
default_lang_id (FK the id of the text in the languages_default table)
text (the translation)
When I execute the following query, I expect to get all of the hungarian translations from the language_translations table and all of the text fields from the language_default table with a null value where there is no hungarian translation.
SELECT `language_translations`.`text`
, `language_default`.`text`
FROM `languages`
, `language_translations`
RIGHT JOIN `language_default` ON `language_default`.`id` = `language_translations`.`default_lang_id`
WHERE `languages`.`code` = 'hu'
AND `languages`.`id` = `language_translations`.`lang_id`
Instead I only get text from the language_default table where there are translations for that text in the tranlsation table. I would expect that behaviour from a left join or normal join but not a right join. Any ideas why I am not getting all of the entries from the langugage_defailt table?
First of all you are using combination of normal join and rights join in wrong way. You can use as per below query.
2nd thing right join means you will get all record from right side and corresponding records from left side and if left side does not have corresponding record then it will show NULL.
Left join is its reverse.
Normal join or comma join will provide only common rows.
So if your tables only have common rows then all joins will provide same results.
SELECT
`language_translations`.`text` , `language_default`.`text`
FROM `languages` AS l
JOIN `language_translations` AS t
ON l.`id` = t.`lang_id` AND l.`code` = 'hu'
RIGHT JOIN `language_default` AS d
ON d.`id` = t.`default_lang_id`;
Don't mix implicit joins and explicit joins. A simple rule is: don't use , in the from clause. The following restructures your query to use left outer join:
SELECT `language_translations`.`text`, ld.`text`
FROM language_default ld left outer join
language_translations lt
on ld.`id` = lt.`default_lang_id` left outer join
`languages` l
on l.`id` = lt.`lang_id` and l.`code` = 'hu' ;
When using outer joins, you need to be very careful about where additional conditions go. Conditions on the driving table (the first a left outer join, the last for a right outer join) can go in the where clause. For other tables, the conditions should go in the on clause. Otherwise, they turn the outer join into an inner for the simple reason that (almost) any comparison to NULL is equivalent to false.

MySQL include zero rows when using COUNT with GROUP BY

I am trying to perform a query which groups a set of data by an attribute called type_id.
SELECT
vt.id AS voucher_type,
COALESCE(COUNT(v.id), 0) AS vouchers_remaining
FROM
vouchers v
INNER JOIN voucher_types vt
ON vt.id = v.type_id
WHERE
v.sold = 0
GROUP BY vt.id
What I want in the result is the type_id and the number of unsold products remaining for each type. This is working OK provided that there is at least one left, however if there is a zero count row, it is not returned in the result set.
How can I set up a dummy row for those types which do not have any corresponding rows to count?
Any advice would be greatly appreciated.
Thanks
You'll have to use a LEFT JOIN instead of an INNER JOIN. You start by selecting all voucher_types and then left join to find the count.
SELECT
voucher_types.id AS voucher_type,
IFNULL(vouchers_count.vouchers_remaining, 0) AS vouchers_remaining
FROM
voucher_types
LEFT JOIN
(
SELECT
v.type_id AS voucher_type,
COUNT(v.id) AS vouchers_remaining
FROM
vouchers v
WHERE
v.sold = 0
GROUP BY v.type_id
) AS vouchers_count
ON vouchers_count.voucher_type = voucher_types.id
You want an OUTER JOIN (or LEFT JOIN, same difference) instead of an INNER JOIN. That should already do the trick.
Because you're doing an INNER JOIN you automatically exclude types with no corresponding vouchers. You need a RIGHT OUTER JOIN.
Also, as far as I can remember, COUNT will always give you an integer, so there is no need for the COALESCE.
Good luck,
Alin