Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySql. How to use Self Join

I need to use Self Join on this table.

+------------+------+--------+
| Country    | Rank |  Year  |
+------------+------+--------+
|France      |  55  |  2000  |
+------------+------+--------+
|Canada      |  30  |  2000  |
+------------+------+--------+ 
|Liberia     |  59  |  2001  |
+------------+------+--------+ 
|Turkey      |  78  |  2000  |
+------------+------+--------+ 
|Japan       |  65  |  2003  |
+------------+------+--------+
|Romania     |  107 |  2001  |
+------------+------+--------+

I need to use self join to get what countries has the same year as Turkey. Display the Country and year only.

This is what I am trying to do.

SELECT DISTINCT a.Country, a.Year 
FROM table1 AS a, table1 AS b 
WHERE a.Year=b.Year and a.Country='Turkey';

^ googled self join, and made it.

I am getting only Turkey. What am I doing wrong?

like image 851
hank99 Avatar asked May 22 '13 21:05

hank99


People also ask

Why do we use self join in MySQL?

In MySQL, Self-Join is important to query ordered data by comparing rows in the same table. The SQL query for Self-Join is applied in a table to itself showing as if there are two tables where using temporary names as alias for the same table in SQL statement.

How do you do a self join?

The self join, as its name implies, joins a table to itself. To use a self join, the table must contain a column (call it X) that acts as the primary key and a different column (call it Y) that stores values that can be matched up with the values in Column X.

How use self join in SQL with example?

SELF JOIN syntax To perform a SELF JOIN in SQL, the LEFT or INNER JOIN is usually used. SELECT column_names FROM Table1 t1 [INNER | LEFT] JOIN Table1 t2 ON join_predicate; Note: t1 and t2 are different table aliases for the same table. You can also create the SELF JOIN with the help of the WHERE clause.

How does self join work in SQL?

A self join is a join in which a table is joined with itself (which is also called Unary relationships), especially when the table has a FOREIGN KEY which references its own PRIMARY KEY. To join a table itself means that each row of the table is combined with itself and with every other row of the table.


2 Answers

You're so close!

Since you say you're displaying the country and year from A and limiting by A. Country of Turkey, Turkey is all you're going to see. You either need to change the selects to be B.country and B.year or change the where clause to be B.country.

This is using a cross join which will get slower the more records there are in a table.

SELECT DISTINCT b.Country, b.Year 
FROM table1 AS a, 
     table1 AS b 
WHERE a.Year=b.Year 
  and a.Country='Turkey';

could be written as... and would likely have the same execution plan.

SELECT DISTINCT b.Country, b.Year 
FROM table1 AS a 
CROSS JOIN table1 AS b 
WHERE a.Year=b.Year 
  and a.Country='Turkey';

OR This uses an INNER JOIN which limits the work the engine must do and doesn't suffer from performance degradation that a cross join would.

SELECT DISTINCT a.Country, a.Year 
FROM table1 AS a 
INNER JOIN table1 AS b 
   on a.Year=b.Year 
  and b.Country='Turkey';

WHY:

Consider what the SQL engine will do when the join occurs A B

+------------+------+--------+------------+------+--------+
| A.Country  | Rank |  Year  | B.Country  | Rank |  Year  |
+------------+------+--------+------------+------+--------+
|France      |  55  |  2000  |France      |  55  |  2000  |
+------------+------+--------+------------+------+--------+
|Canada      |  30  |  2000  |France      |  55  |  2000  |
+------------+------+--------+------------+------+--------+ 
|Turkey      |  78  |  2000  |France      |  55  |  2000  |
+------------+------+--------+------------+------+--------+ 
|France      |  55  |  2000  |Canada      |  30  |  2000  |
+------------+------+--------+------------+------+--------+
|Canada      |  30  |  2000  |Canada      |  30  |  2000  |
+------------+------+--------+------------+------+--------+ 
|Turkey      |  78  |  2000  |Canada      |  30  |  2000  |
+------------+------+--------+------------+------+--------+ 
|France      |  55  |  2000  |Turkey      |  78  |  2000  |
+------------+------+--------+------------+------+--------+
|Canada      |  30  |  2000  |Turkey      |  78  |  2000  |
+------------+------+--------+------------+------+--------+ 
|Turkey      |  78  |  2000  |Turkey      |  78  |  2000  |
+------------+------+--------+------------+------+--------+ 

So when you said display A.Country and A.Year where A.Country is Turkey, you can see all it can return is Turkey (due to the distinct only 1 record)

But if you do B.Country is Turkey and display A.Country, you'll get France, Canada and Turkey!

like image 132
xQbert Avatar answered Oct 16 '22 23:10

xQbert


Change a.Country = 'Turkey' to b.Country = 'Turkey'

You have SELECT DISTINCT a.Country, but your condition is a.Country = 'Turkey'. Even if you do get multiple rows, they are filtered by the DISTINCT

like image 32
Explosion Pills Avatar answered Oct 16 '22 22:10

Explosion Pills