Handle NULL in JOIN - mysql

I have the following query:
SELECT item.`ID`, item.`Name`, item.`UnitCost`,
item.`Price`, discount.`rate`
FROM item
INNER JOIN discount ON discount.`ID`=item.`DiscountID`
WHERE item.`Code`=itemCode;
If discount is not assign to the item (MEANS NULL), the above query does not return any row.
How can Change my query to handle null? and in case of null, item.discountID must be return 0?

Use a LEFT JOIN instead of an INNER JOIN:
SELECT item.`ID`, item.`Name`, item.`UnitCost`,
item.`Price`, IFNULL(discount.`rate`, 0)
FROM item
LEFT JOIN discount ON discount.`ID`=item.`DiscountID`
WHERE item.`Code`=itemCode;
A LEFT JOIN returns all rows from the first table, even if there are no matches in the joined table.

The problem is the inner join. Try a left join or right join imstead when you have this issue

Do it with LEFT JOIN.
SELECT item.`ID`, item.`Name`, item.`UnitCost`, item.`Price`, discount.`rate`
FROM item LEFT JOIN discount ON item.`DiscountID`=discount.`ID`
WHERE item.`Code`=itemCode;

Use LEFT JOIN instead of INNER JOIN. INNER JOIN just return rows when there is at least one match in both tables
COALESCE() will convert all the null values to 0
try this
SELECT item.`ID`, item.`Name`, item.`UnitCost`,
item.`Price`, COALESCE(discount.`rate` , 0)
FROM item
LEFT JOIN discount ON discount.`ID`=item.`DiscountID`
WHERE item.`Code`=itemCode;

Related

Get Record only if its Join record exists in other table

I have two tables for Groups and Category i wanted to return the groups and categories excluding those groups which doesn't have any category here is the SQL i wrote:
SELECT
cat_group.subject as group_name , spcat . *
FROM
special_event_groups AS cat_group
LEFT JOIN
special_event_categories AS spcat ON cat_group.id = spcat.group_id
AND cat_group.partner_id = spcat.partner_id;
Its returning me the records of group with NULL values which doesn't have any category. Do i need to use a subquery ?
What you need to do is to change LEFT JOIN to JOIN:
SELECT
cat_group.subject as group_name , spcat . *
FROM
special_event_groups AS cat_group
JOIN
special_event_categories AS spcat ON cat_group.id = spcat.group_id
AND cat_group.partner_id = spcat.partner_id;
If joining condition is not met, LEFT JOIN show row from special_event_groups and attach NULL values in selected columns from special_event_categories. JOIN, on the other hand, never returns row when JOIN condition is not met. You can read #MrMoose comment for more info.
You can use OUTER LEFT JOIN too, LEFT JOIN, JOIN, it depends on the version of your database.
Try this:
SELECT
cat_group.subject as group_name , spcat . *
FROM
special_event_groups AS cat_group
// LEFT JOIN, OUTER LEFT JOIN, JOIN
special_event_categories AS spcat ON cat_group.id = spcat.group_id
WHERE cat_group.partner_id IS NULL;
Let me know if it worked

Duplicates in a LEFT JOIN

I am using LEFT JOIN to join two tables but it is returning a few duplicates. This is my query:
SELECT tblDrill.Hole_ID, tblAssay.MidPoint, tblAssay.SampleNumber, tblAssay.Gold, tblMagSus.MagSus
FROM tblDrill LEFT JOIN tblMagSus ON (((tblAssay.MidPoint)>tblMagSus.From And (tblAssay.MidPoint)<tblMagSus.To)) AND (tblAssay.Hole_ID = tblMagSus.Hole_ID);
A few times, there is more than one tblAssay.MidPoint that falls between the tblMagSus.From and tblMagSus.To so it returns two records. I only want it to return the record that contains the highest MagSus value.
Perhaps SELECT DISTINCT would be appropriate
http://www.w3schools.com/sql/sql_distinct.asp
SELECT DISTINCT tblDrill.Hole_ID, tblAssay.MidPoint, tblAssay.SampleNumber, tblAssay.Gold, tblMagSus.MagSus
FROM tblDrill LEFT JOIN tblMagSus ON (((tblAssay.MidPoint)>tblMagSus.From And (tblAssay.MidPoint)<tblMagSus.To)) AND (tblAssay.Hole_ID = tblMagSus.Hole_ID);

Query with joins

I am running a query:
select course.course,iars.id,
students.rollno,
students.name as name,
teachers.name as tname,
students.studentid,
attndata.studentid ,sum(attndata.obt) as obt
sum(attndata.benefits) as ben , (sum(attndata.max)) as abc
from groups, students
left join iars
on iars.id
left join str
on str.studentid=students.studentid
left join course
on course.c_id=students.course
left join teachers
on teachers.id=iars.teacherid
join sgm
on sgm.studentid=students.studentid
left join attndata
on attndata.studentid=students.studentid and iars.id=attndata.iarsid
left join sps
on sps.studentid=students.studentid and iars.paperid=sps.paperid
left join semdef
on semdef.semesterid=str.semesterid
where students.course='1'
and students.status='regular'
and sps.paperid='5'
and iars.courseid=students.course
and iars.semester=str.semesterid
and semdef.month=9
and iars.paperid='5'
and str.semesterid='1'
and str.sessionid='12'
and groups.id=sgm.groupid
group by sps.studentid,
teachers.id,
semdef.month
order by
students.name
In this query whenever I am having left join on semdef.id=attndata.mon, I am getting zero result when the value of semdef.id=null but I want all the results, irrespective of semdef, but I want to use it. As in it should fetch result, if the values are null. Can you please help it out.
It's probably because your where clause is saying
and semdef.month=9
and you probably want
and (semdef.month=9 OR semdef.id IS NULL)
or something similar.
It's because your where clause has statements relating to the semdef table. Add these to the join clause as putting these in the where is implying an inner join.
Eg:
Left join semdef on xxx and semdef.id = attndata.min

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

Left Join not returning all rows

I have this query in MySQL:
SELECT pr.*, pr7.value AS `room_price_high`
FROM `jos_hp_properties` pr
LEFT OUTER JOIN `jos_hp_properties2` pr7 ON pr7.property=pr.id
WHERE pr7.field=23
The jos_hp_properties table has 27 rows but the query only returns one. Based on this question I think it may be because of the WHERE clause. The jos_hp_properties2 table has fields id, property, field, value, where field is a foreign key to a third table (which I don't need to get data from).
Is there a way to select all the rows from the first table, including the value from table #2 where the field is 23 (or NULL if there is no field 23)?
Sure. Move the WHERE condition to the JOIN:
SELECT pr.*, pr7.value AS `room_price_high`
FROM `jos_hp_properties` pr
LEFT JOIN `jos_hp_properties2` pr7
ON pr7.property=pr.id
AND
pr7.field=23
You must place the pr7 criteria in the join, not in the where clause. The where clause works on the entire result set AFTER the join has been performed.
SELECT pr.*, pr7.value AS `room_price_high`
FROM `jos_hp_properties` pr
LEFT OUTER JOIN `jos_hp_properties2` pr7 ON pr7.property=pr.id and pr7.field=23
Try this:
SELECT pr.*, pr7.value AS `room_price_high`
FROM `jos_hp_properties` pr
LEFT OUTER JOIN `jos_hp_properties2` pr7 ON pr7.property=pr.id
WHERE (pr7.field=23 OR pr7.field is null)
You can also use a CTE (Common Table Expression) to do the select, then use the CTE to do the left join..
wrc (parentid, childid) as (
select parentid, childid
from placechild
where relationshipid in (select id from placerelationship where relationship = 'Winter Region Capital')
),
stw (cnid, coid, capid, st_or_te, sid, scid,wcid) as (
select s.cnid, s.coid, s.capid, s.st_or_te, s.sid, s.scid, w.childid
from stcap s
left join wrc w
on s.sid = w.parentid
)
select * from stw