Left Join query not working - mysql

I have 2 tables.
Table 1:
ID Name Age PhoneNumber
12 Joe 25 873827382
23 Bob 28 928398233
34 Jane 23 237828883
Table 2:
ID Agent QuantitySold
12 A1 100
23 B1 300
12 C1 600
34 A2 400
34 B1 800
23 B2 900
I want to show all the details of the employees who have never sold a quantity not equal to 800.
SELECT a.ID, a.Name, a.Age, a.PhoneNumber
FROM table1 a LEFT JOIN table2 b
ON a.ID= b.ID AND b.quantity <> 800
I want a result set that doesn't have ID 34 in it. But I cant seem to achieve that. Any help?

You need to change your Left Join to Inner Join.
Left Join will bring all the rows from table1 even though he never made a sales. I will do this using Exists.
SELECT a.ID,
a.Name,
a.Age,
a.PhoneNumber
FROM table1 a
WHERE EXISTS (SELECT 1
FROM table2 b
WHERE a.ID = b.ID
AND b.quantity <> 800)

You can use NOT EXISTS without any of the JOINs:
SELECT a.ID
, a.Name
, a.Age
, a.PhoneNumber
FROM table1 a
WHERE NOT EXISTS (SELECT * FROM table2 WHERE ID = a.ID AND QuantitySold = 800)
By the way, the column name is QuantitySold, not quantity.
JSFiddle

This is what finally worked.
SELECT a.ID
, a.Name
, a.Age
, a.PhoneNumber
FROM table1 a
WHERE a.ID NOT IN (SELECT ID FROM table2 QuantitySold = 800);

Why you are using Left Join. Use inner join rather. Something like this:-
SELECT a.ID, a.Name, a.Age, a.PhoneNumber, SUM(b.quantity)
FROM table1 a JOIN table2 b
ON a.ID= b.ID
GROUP BY b.Agent
HAVING SUM(b.quantity) <> 800

Related

How to left join when only matched one record from right table

I want to know How to left join when only matched one record from right table.
For example,
tableA
id
value
1
34
2
42
3
60
tableB
id
value
tableA_id
1
20
1
2
31
1
3
50
2
I want to get result like below using left outer join.
tableA_id
tableA_value
tableB_value
1
34
null
2
42
50
3
60
null
tableB_value of first row is null, because tableA.id = tableB.tableA_id matches multiple records.
how to solve it ?
Thanks.
You can make use of COUNT() as an analytic function to keep track of how many times a tableA_id occurs in the A table:
SELECT a.id AS tableA_id, a.value AS tableA_value, b.value AS tableB_value
FROM tableA a
LEFT JOIN
(
SELECT *, COUNT(*) OVER (PARTITION BY tableA_id) cnt
FROM tableB
) b
ON a.id = b.tableA_id AND b.cnt = 1
ORDER BY a.id;
Demo
You can do this using aggregation on the b table as well:
SELECT a.id AS tableA_id, a.value AS tableA_value, b.value AS tableB_value
FROM tableA a LEFT JOIN
(SELECT tableA_id, MAX(value) as value
FROM tableB
GROUP BY tableA_id
HAVING COUNT(*) = 1
) b
ON a.id = b.tableA_id
ORDER BY a.id;
This works because if there is only one row in B for a given id, then MAX() returns the value on that row.

Why LEFT OUTER JOIN reduces rows from left table?

Just want to show all data in table A and LEFT JOIN table B with coorelate subquery but fail to get all data in table A
SELECT a.id FROM tableA a
LEFT JOIN tableB b1 ON a.id = b1.id
WHERE date = (SELECT MAX(date) FROM tableB b2 WHERE b1.id= b2.id)
tableA
id
======
1001
1002
1003
1004
tableB
id date
=============
1001 20160101
1001 20160102
1003 20160102
1003 20160105
Expected Result
id date
===============
1001 20160102
1002 NULL
1003 20160105
1004 NULL
Engine Return
id date
=============
1001 20160102
1003 20160105
What I would do is a left join on a subselect, that only contains the max date per id like this:
SELECT a.id, b.maxdate FROM tableA a
LEFT JOIN (SELECT id, MAX(date) AS 'maxdate' FROM tableB2 GROUP BY id) b ON a.id = b.id
This should also be quicker, since the select for the join will only be executed once while the select in a where clause will be executed for each row.
update your query to be:
SELECT a.id, b1.date FROM tableA a
LEFT outer JOIN tableB b1 ON a.id = b1.id
WHERE date = (SELECT MAX(date) FROM tableB b2 WHERE b1.id= b2.id) or date is null
The where clause applies on the joined dataset, therefore your where condition removes those records from the resultset, that do not match the criteria.
I would move your subquery to the from clause:
SELECT a.id FROM tableA a
LEFT JOIN (SELECT MAX(date) as mdate, id FROM tableB GROUP BY id) b1 ON a.id = b1.id

SQL join table to selected records

Example:
SELECT SUM(SALARY) FROM (SELECT * FROM table1 WHERE id > 10) a LEFT JOIN table2 b on a.person = b.person
I want join table2 records only to (SELECT * FROM table1 WHERE id > 10) records, my example is not correct.
table1 contain 100mln records and I cant join table2 to all records I must use subquery
I'm assuming, you salary is not summing up correctly (you are getting more than you expect). This is because LEFT JOIN will leave NULL for the rowsthat doesn't have match in b.
For this SQL:
SELECT a.*, b.*
FROM (select * from (SELECT 123 AS Salary,
'Tom' AS person
UNION
SELECT 343 AS Salary,
'Bob' AS person
UNION
SELECT 877 AS Salary,
'Tom' AS person) as t where t.Salary > 123) a
LEFT JOIN (SELECT *
FROM (SELECT 'Tom' AS person,
1 AS id
UNION
SELECT 'Bob' AS person,
2 AS id) AS t
WHERE t.id = 1) AS b
ON a.person = b.person
you will have this output:
So INNER JOIN should work for you.
SELECT SUM(SALARY) FROM (SELECT * FROM table1 WHERE id > 10) a
LEFT JOIN table2 b on a.person = b.person
Hopefully this will get you going in the correct direction....
select sum(a.salary)
from table1 a
left join table2 b on a.person = b.person and b.salary_type = "something"
where a.id > 10
;

All conditional data required in mysql

I have three table a,b,c having id common between them.
Table a:-
id name value
1 a 4
2 v 6
Table b:-
id abc
2 54
3 56
Table c:-
id bcd
1 54
3 34
Now what i want is what ever is id in where condition, data comes from all tables.
Please advice me how to do that.
Expected Result-
if query is
select * from a left join b on a.id=b.id left join c on a.id=c.id where b.id=3
id name value bcd abc
3 NULL NULL 34 56
if query is
select * from a left join b on a.id=b.id left join c on a.id=c.id where a.id=1
id name value bcd abc
3 a 4 54 NULL
What about this approach to the problem? :)
SELECT
z.id,
a.name,
a.value,
c.bcd,
b.abc
FROM
(
SELECT
DISTINCT y.id id
FROM
(
SELECT id FROM a
UNION ALL
SELECT id FROM b
UNION ALL
SELECT id FROM c
) y
) z
LEFT JOIN a ON z.id = a.id
LEFT JOIN b ON z.id = b.id
LEFT JOIN c ON z.id = c.id
where z.id = 3
sql fiddle
This way you just need to give the query the number not caring about which tables it exists in.
It's depends on what you are setting in WHERE condition. If you are setting WHERE b.ID = 3 then you need to join other tables with B like this:
SELECT A.ID AS A_ID,A.Name, A.value
,B.Id as B_ID,B.abc
,C.id AS C_ID, c.bcd
FROM b
LEFT JOIN a ON a.id = b.id
LEFT JOIN c ON a.id = c.id
WHERE b.id=3;
This is happens because b.ID = 3 is not in Table A and Table C is joined with Table A.
If you set Table A.ID = 1 then you have to join other tables with A using LEFT JOIN like this:
SELECT A.ID AS A_ID,A.Name, A.value
,B.Id as B_ID,B.abc
,C.id AS C_ID, c.bcd
FROM A
LEFT JOIN B ON a.id = b.id
LEFT JOIN c ON a.id = c.id
WHERE A.id=1;
See this SQLFiddle
This is technically impossible, when you are using ID in where how can you get data in case there Id not present in any of the perticular table, you are changing the logic of where ;).
But what you can do is
SELECT * FROM
(SELECT AID AS ID,NAME,VALUE FROM A
UNION
SELECT BID as ID,NAME,NULL AS VALUE FROM B
UNION
SELECT CID as ID,NAME ,NULL AS VALUE FROM C)
WHERE ID =''
Hope this helps
else please clarify. what you want.
Regards
Ashutosh Arya
I will try to guess, even though I barely find an explanation to the expected result:
SELECT
b.id,
a.name,
a.value,
c.bcd,
b.abc
FROM
b
INNER JOIN c ON b.id = c.id
LEFT JOIN a ON b.id = a.id
sql fiddle

Complex MySQL query using group by

Lets say i have two tables
Table1:
product_id, design1, design2
1 A C
2 B A
Table2:
product_id, value
1 10
2 10
Now i want to to sum all the value for particular design for all products.
SELECT designA, SUM(value) FROM (
SELECT b.design1 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design1) AS T GROUP BY designA
It gives me this:
designA SUM(value)
A 10
B 10
Now the problem is that if user has specified design2 in table1 then what ever is the value of design1 will automatically be added in design2. If design2 is not present design1 column then it will be a new row of result:
Desited result is this:
designA SUM(value)
A 20
B 10
C 10
select y.designA, sum(value) from
(select a.design1 as designA, value from
Table1 as a
inner join Table2 as b
on
a.product_id = b.product_id
union all
select a.design2 as designA, value from
Table1 as a
inner join Table2 as b
on
a.product_id = b.product_id) as y
group by y.designA
seems to work for your test data, not tried on other configurations but you should be able to tweak it, if you understand what it's doing.
UNION in the matches based on design2:
SELECT designA, SUM(value) FROM (
SELECT b.design1 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design1
UNION
SELECT b.design2 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design2
) AS T GROUP BY designA