Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL JOIN ON vs USING?

Tags:

join

mysql

using

In a MySQL JOIN, what is the difference between ON and USING()? As far as I can tell, USING() is just more convenient syntax, whereas ON allows a little more flexibility when the column names are not identical. However, that difference is so minor, you'd think they'd just do away with USING().

Is there more to this than meets the eye? If yes, which should I use in a given situation?

like image 879
Nathanael Avatar asked Jul 06 '12 16:07

Nathanael


People also ask

When to use on or using with joins?

In general, we use ON in MySQL. In Joins, we use ON in a set of columns. USING is useful when both the tables share a column of the exact same name on which they join.

What is the difference between join on and join using in SQL?

In a nutshell, you use ON for most things, but USING is a handy shorthand for the situation where the column names are the same. The example above uses the ON keyword, but since the columns we use to join are called owners_id in both tables, then we can instead put in USING as a shorthand.

Is there any difference if you are adopting using keyword in join condition instead of using on keyword for join condition?

The main difference between USING and ON in a join condition is that when SELECT * is used in a query with a USING join, the resulting table will only have one instance of the column specified in the USING condition.


2 Answers

It is mostly syntactic sugar, but a couple differences are noteworthy:

ON is the more general of the two. One can join tables ON a column, a set of columns and even a condition. For example:

SELECT * FROM world.City JOIN world.Country ON (City.CountryCode = Country.Code) WHERE ... 

USING is useful when both tables share a column of the exact same name on which they join. In this case, one may say:

SELECT ... FROM film JOIN film_actor USING (film_id) WHERE ... 

An additional nice treat is that one does not need to fully qualify the joining columns:

SELECT film.title, film_id -- film_id is not prefixed FROM film JOIN film_actor USING (film_id) WHERE ... 

To illustrate, to do the above with ON, we would have to write:

SELECT film.title, film.film_id -- film.film_id is required here FROM film JOIN film_actor ON (film.film_id = film_actor.film_id) WHERE ... 

Notice the film.film_id qualification in the SELECT clause. It would be invalid to just say film_id since that would make for an ambiguity:

ERROR 1052 (23000): Column 'film_id' in field list is ambiguous

As for select *, the joining column appears in the result set twice with ON while it appears only once with USING:

mysql> create table t(i int);insert t select 1;create table t2 select*from t; Query OK, 0 rows affected (0.11 sec)  Query OK, 1 row affected (0.00 sec) Records: 1  Duplicates: 0  Warnings: 0  Query OK, 1 row affected (0.19 sec) Records: 1  Duplicates: 0  Warnings: 0  mysql> select*from t join t2 on t.i=t2.i; +------+------+ | i    | i    | +------+------+ |    1 |    1 | +------+------+ 1 row in set (0.00 sec)  mysql> select*from t join t2 using(i); +------+ | i    | +------+ |    1 | +------+ 1 row in set (0.00 sec)  mysql> 
like image 92
Shlomi Noach Avatar answered Oct 01 '22 22:10

Shlomi Noach


Thought I would chip in here with when I have found ON to be more useful than USING. It is when OUTER joins are introduced into queries.

ON benefits from allowing the results set of the table that a query is OUTER joining onto to be restricted while maintaining the OUTER join. Attempting to restrict the results set through specifying a WHERE clause will, effectively, change the OUTER join into an INNER join.

Granted this may be a relative corner case. Worth putting out there though.....

For example:

CREATE TABLE country (    countryId int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,    country varchar(50) not null,   UNIQUE KEY countryUIdx1 (country) ) ENGINE=InnoDB;  insert into country(country) values ("France"); insert into country(country) values ("China"); insert into country(country) values ("USA"); insert into country(country) values ("Italy"); insert into country(country) values ("UK"); insert into country(country) values ("Monaco");   CREATE TABLE city (   cityId int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,   countryId int(10) unsigned not null,   city varchar(50) not null,   hasAirport boolean not null default true,   UNIQUE KEY cityUIdx1 (countryId,city),   CONSTRAINT city_country_fk1 FOREIGN KEY (countryId) REFERENCES country (countryId) ) ENGINE=InnoDB;   insert into city (countryId,city,hasAirport) values (1,"Paris",true); insert into city (countryId,city,hasAirport) values (2,"Bejing",true); insert into city (countryId,city,hasAirport) values (3,"New York",true); insert into city (countryId,city,hasAirport) values (4,"Napoli",true); insert into city (countryId,city,hasAirport) values (5,"Manchester",true); insert into city (countryId,city,hasAirport) values (5,"Birmingham",false); insert into city (countryId,city,hasAirport) values (3,"Cincinatti",false); insert into city (countryId,city,hasAirport) values (6,"Monaco",false);  -- Gah. Left outer join is now effectively an inner join  -- because of the where predicate select * from country left join city using (countryId) where hasAirport ;   -- Hooray! I can see Monaco again thanks to  -- moving my predicate into the ON select * from country co left join city ci on (co.countryId=ci.countryId and ci.hasAirport) ;  
like image 29
Tom Mac Avatar answered Oct 01 '22 23:10

Tom Mac