MySQL ON против USING?

В MySQL JOIN, в чем разница между ON и USING()? Насколько я могу судить, USING() - это просто более удобный синтаксис, тогда как ON позволяет немного больше гибкости, если имена столбцов не идентичны. Однако это различие настолько незначительно, вы бы подумали, что они просто покончат с USING().

Есть ли что-то большее, чем кажется на первый взгляд? Если да, то какой я должен использовать в данной ситуации?

Ответ 1

В основном это синтаксический сахар, но примечательны несколько различий:

ON является более общим из двух. Можно объединить таблицы в столбце, набор столбцов и даже условие. Например:

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

ИСПОЛЬЗОВАНИЕ полезно, когда обе таблицы имеют столбец с тем же именем, с которым они соединяются. В этом случае можно сказать:

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

Дополнительным приятным удовольствием является то, что не нужно полностью квалифицировать соединительные столбцы:

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

Чтобы проиллюстрировать, чтобы сделать это с помощью ВКЛ, нам нужно написать:

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 ...

Обратите внимание на квалификацию film.film_id в предложении SELECT. Было бы недействительно просто сказать film_id, поскольку это создавало бы двусмысленность:

ОШИБКА 1052 (23000): Столбец 'film_id' в списке полей неоднозначен

Что касается select *, столбец соединения появляется в результирующем наборе дважды с ON, пока он появляется только один раз с 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>

Ответ 2

Думаю, что я бы включил здесь, когда нашел ON более полезным, чем USING. Именно когда OUTER объединяются в запросы.

ON дает преимущества, позволяющие набору результатов таблицы привязать запрос OUTER к ограничению при сохранении соединения OUTER. Попытка ограничить результаты, заданные с помощью предложения WHERE, эффективно заменит соединение OUTER на объединение INNER.

Конечно, это может быть относительный угловой случай. Стоит там, хотя.....

Например:

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)
; 

Ответ 3

В Википедии есть следующая информация о USING:

Конструкция USING больше, чем просто синтаксический сахар, однако, поскольку набор результатов отличается от результирующего набора версии с явный предикат. В частности, любые столбцы, упомянутые в ИСПОЛЬЗОВАНИИ список появится только один раз, с неквалифицированным именем, а не раз для каждой таблицы в соединении. В приведенном выше случае будет один Столбец DepartmentID и ни один сотрудник. department.DepartmentID.

Таблицы, о которых он говорил:

enter image description here

Документация Postgres также определяет их довольно хорошо:

Предложение ON - это наиболее общий вид условия соединения: он принимает Логическое выражение выражения того же типа, что и в WHERE пункт. Пара строк из T1 и T2 соответствует, если выражение ON имеет значение true.

Предложение USING является сокращением, которое позволяет вам воспользоваться преимуществами конкретная ситуация, когда обе стороны объединения используют одно и то же имя для соединительной колонки (столбцов). Он принимает разделенный запятыми список имена общих столбцов и образуют условие объединения, которое включает сравнение равенства для каждого. Например, объединение T1 и T2 с ИСПОЛЬЗОВАНИЕ (a, b) создает условие соединения ON T1.a = T2.a AND T1.b = T2.b.

Кроме того, вывод JOIN USING подавляет избыточные столбцы: нет необходимости печатать обе совпадающие столбцы, так как они должны имеют равные значения. В то время как JOIN ON создает все столбцы из T1 по всем столбцам из T2, JOIN USING создает один выходной столбец для каждого из перечисленных пар столбцов (в указанном порядке), за которыми следуют любые оставшиеся столбцы из T1, за которыми следуют любые оставшиеся столбцы из T2.