Left Join in Mysql? - mysql

This is my first Table.
Then the second one is
Now I am trying to do Left join like this
SELECT t1.StackID FROM t1 LEFT JOIN t2 on t1.StackID=t2.StackID
Output
I am confused here, Is this the correct output? Is not this supposed to return only the 5 rows which is present in left side table.

It's correct output. You are doing LEFT JOIN, so for every record in LEFT table DBMS will 'concatenate' the corresponding RIGHT table record(-s) (and NULL, if there's no corresponding record for the JOIN condition; also remember, that if there are more that 1 corresponding record - all will be joined - this issue is why you're getting not only 5 records from 1-st table).
The thing you're trying to achieve should be done by either DISTINCT modifier, i.e.
SELECT DISTINCT t1.StackID FROM t1 LEFT JOIN t2 ON t1.StackID=t2.StackID;
More about JOIN in SQL you can read here.

There is a simple example of left join:-
SELECT * FROM a JOIN b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key)
WHERE b.key=d.key;

These extra repeated values of StackId are coming from the join, just use DISTINCT to get those only 5 values:
SELECT DISTINCT t1.StackID
FROM t1
LEFT JOIN t2 on t1.StackID=t2.StackID;
SQL Fiddle Demo

Yes, this is the expected output.
To get the distinct IDs, use DISTINCT -
SELECT DISTINCT t1.StackID
FROM t1
LEFT JOIN t2
ON t1.StackID=t2.StackID
When you left joined your t2 table with t1 based on stackID, then the database will join every row of t2 with the every row of t1 which has the same stackID value. Since 1 appears in six rows in the t2 table as a stackID value, all of them are joined with the first row of t1. Similar thing is true for all other values.

To give yourself a little more understanding of how a left join works try this:
SELECT t1.StackID, t2.StackID FROM t1 LEFT JOIN t2 on t1.StackID=t2.StackID
basically a left join returns all the rows from the left table plus matching ones from the right.

Related

MySQL LEFT JOIN a ON b compared to including WHERE a IN (b)

When I run the following query I get 2769 rows returned.
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t2.account_id = t1.account_id;
However, when I add the WHERE clause below, I get 692 Lines returned.
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t2.account_id = t1.account_id
WHERE t2.account_id IN (t1.account_id);
I thought that the condition established by my LEFT JOIN would the same condition established by my WHERE clause (i.e. that these two lines would effectively be redundant).
This is clearly not the case, but I cannot figure out why.
The left join returns all records of t1 and returns null for the columns of t2 for all records where the join could not be made.
But the where clause filters all data, no matter from which table. So when you filter on t2 in your where clause then all records where the join could not be made (and the t2.account_id is null) get excluded from the result since null != t1.account_id.
So basically your where clause turn your left join into an inner join.

MySQL JOIN Complexity

I am using MySQL 5.5 and have two tables T1(ID, NAME) and T2(ID, MARKS), following is the data in the table.
T1's data
ID NAME
1 A
2 B
3 C
T2's data
ID MARKS
1 40
5 60
AND I want following resultset
ID NAME MARKS
1 A 40
2 B 0
3 C 0
What query we can write to accomplish above resultset?
LEFT JOIN the two tables:
SELECT
t1.id,
t1.name,
IFNULL(t2.Marks, 0) AS Marks
FROM T1
LEFT JOIN T2 ON t1.ID = t2.ID;
SQL Fiddle Demo
You should be using a LEFT JOIN clause for this kind of result :-)
Your query will look like this :
SELECT
ID,
NAME,
COALESCE(MARKS, 0) AS MARKS
FROM T1
LEFT JOIN T2 USING(ID)
Note that I'm using the USING clause for a more semantic and compact syntax than the ON clause.
In this case, you need to use LEFT JOIN to join both tables since it is not guaranteed that ID on table T1 will exist on table T2. LEFT JOIN retrieves all rows that are found on the lefthand side table whether it has a matching record or not on the righthand side table.
The use of COALESCE in the statement is to convert NULL values into 0. The reason why NULL exist on the values of the column is because some records on table T1 doesn't have a matching record on table T2 causing the column T2.Marks to be null.
SELECT a.ID, a.Name, COALESCE(b.Marks, 0) Marks
FROM T1 a
LEFT JOIN T2 b
ON a.ID = b.ID
SQLFiddle Demo
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins

How to use INNER/OUTER JOIN in MYSQL

I have 3 tables which contain different types of data related to each other. the tables populate via an excel spreadsheet. I have:
table1 table2 table3
item_number item_number item_number
desc desc qty_sold
qty_instock vdf_cost upc
cost status
What I'm trying to do is use a join function to show all the data as they relate to each other, except the problem is that when I run
SELECT *
FROM table1 a
INNER JOIN table2 b
ON a.someColumn = b.otherColumn
INNER JOIN table3 c
ON b.anotherColumn = c.nextColumn
It just puts the tables side by side, If I run
SELECT *
FROM table1 a
INNER JOIN table2 b
USING(item_number)
It works but only joins the item number (i have no idea how to use multiple fields such as description which repeats), and for some reason I can only use the two tables when I try to add a third table (most likely being done completely wrong)
SELECT *
FROM table1 a
INNER JOIN table2 b
INNER JOIN table3 c
USING(item_number)
I just get a syntax error.
Thanks for all the help in advance
UPDATE:
I got it working
SELECT *
FROM master_list a
INNER JOIN bby_report ab USING (item_number, description)
INNER JOIN sales_report b USING (item_number)
Is there a way I can exclude the description from one of the tables and keep it from another one? Turns out the descriptions are not an exact match from one table to a another so it keeps returning zero results.
So to clarify keep description from table1 and leave out description from table2 while being able to JOIN the fields based on item_number
SELECT *
FROM master_list a
INNER JOIN bby_report ab USING (item_number, description)
INNER JOIN sales_report b USING (item_number)

MySQL: different results with a WHERE statement included in master-detail query?

Let's say I have a mastertable (table1) with a detailtable (table2). There can be multiple detail records for each masterrecord. Now I want a query that counts all detailrecords for each masterrecord :
SELECT t1.id, count(t2.*)
FROM table1 as t1
LEFT JOIN table2 AS t2 ON t2.id=t1.id
GROUP BY t1.id
This gives me exactly the same number of records as table1 has.
But when I add a WHERE statement to only count the records that have a checkfield that's higher than 0, I don't get all records in table1 anymore! The ones with no matching detailrecords are now left out completely. Why is this happening?
SELECT t1.id, count(t2.*)
FROM table1 as t1
LEFT JOIN table2 AS t2 ON t2.id=t1.id
WHERE t2.checkfield != 0
GROUP BY t1.id
(Maybe something else is wrong in my real query, since I tried to simplify it for this example, but I think I got it right)
The WHERE clause restricts the joined results which are being aggregated over, so while you're trying do an outer join, only those rows with t2.checkfield != 0 survive, but that excludes all the unmatched rows!
On the other hand, when you change WHERE to AND, you now have tab1 LEFT OUTER JOIN tab2 ON(tab1.id = tab2.t1_id AND some_condition) -- but this is still an outer join, i.e. records on the left which have no match on the right will be included.

How to retrieve non-matching results in mysql

I'm sure this is straight-forward, but how do I write a query in mysql that joins two tables and then returns only those records from the first table that don't match. I want it to be something like:
Select tid from table1 inner join table2 on table2.tid = table1.tid where table1.tid != table2.tid;
but this doesn't seem to make alot of sense!
You can use a left outer join to accomplish this:
select
t1.tid
from
table1 t1
left outer join table2 t2 on
t1.tid = t2.tid
where
t2.tid is null
What this does is it takes your first table (table1), joins it with your second table (table2), and fills in null for the table2 columns in any row in table1 that doesn't match a row in table2. Then, it filters that out by selecting only the table1 rows where no match could be found.
Alternatively, you can also use not exists:
select
t1.tid
from
table1 t1
where
not exists (select 1 from table2 t2 where t2.tid = t1.tid)
This performs a left semi join, and will essentially do the same thing that the left outer join does. Depending on your indexes, one may be faster than the other, but both are viable options. MySQL has some good documentation on optimizing the joins, so you should check that out..