MySQL EN vs USANDO?


En un MySQL JOIN, ¿cuál es la diferencia entre ON y USING()? Por lo que puedo decir, USING() es simplemente una sintaxis más conveniente, mientras que ON permite un poco más de flexibilidad cuando los nombres de las columnas no son idénticos. Sin embargo, esa diferencia es tan pequeña, que pensarías que acabarían con USING().

¿Hay más en esto de lo que parece? En caso afirmativo, ¿cuál debo usar en una situación determinada?

Author: Nathanael, 2012-07-06

4 answers

Es principalmente azúcar sintáctica, pero un par de diferencias son notables:

ON es el más general de los dos. Se pueden unir tablas EN una columna, un conjunto de columnas e incluso una condición. Por ejemplo:

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

USAR es útil cuando ambas tablas comparten una columna con el mismo nombre exacto en la que se unen. En este caso, uno puede decir:

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

Un buen trato adicional es que uno no necesita calificar completamente la unión columnas:

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

Para ilustrar, hacer lo anterior con EN, tendríamos que escribir:

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

Observe la calificación film.film_id en la cláusula SELECT. Sería inválido decir simplemente film_id ya que eso daría lugar a una ambigüedad:

ERROR 1052 (23000): La columna 'film_id' en la lista de campos es ambigua

En cuanto a select *, la columna de unión aparece en el conjunto de resultados dos veces con ON mientras que solo aparece una vez con 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>
 305
Author: Shlomi Noach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-10 07:57:03

Pensé que iba a chip aquí con cuando he encontrado ON para ser más útil que USING. Es cuando OUTER se introducen combinaciones en las consultas.

ON se beneficia de permitir que el conjunto de resultados de la tabla en la que se une una consulta OUTER se restrinja mientras se mantiene la unión OUTER. Intentar restringir el conjunto de resultados mediante la especificación de una cláusula WHERE cambiará, efectivamente, la combinación OUTER en una combinación INNER.

Concedido esto puede ser un caso de esquina relativa. Vale la pena ponerlo ahí.....

Por ejemplo:

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)
; 
 12
Author: Tom Mac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-12 11:15:59

Wikipedia tiene la siguiente información sobre USING:

La construcción DE USO es más que mero azúcar sintáctico, sin embargo, ya que el conjunto de resultados difiere del conjunto de resultados de la versión con el predicado explícito. Específicamente, cualquier columna mencionada en el USO la lista aparecerá solo una vez, con un nombre no calificado, en lugar de una vez para cada tabla en la unión. En el caso anterior, habrá una sola Columna DepartmentID y ningún empleado.Departamento o Departamento.Departamento.

Tablas de las que hablaba:

introduzca la descripción de la imagen aquí

La documentación de Postgres también los define bastante bien:

La cláusula ON es el tipo más general de condición join: toma una Expresión de valor booleano del mismo tipo que se usa en un clausula. Un par de filas de T1 y T2 coinciden si la expresión ON se evalúa como verdadero.

La cláusula USING es una abreviatura que le permite aprovechar de la situación específica en la que ambos lados de la unión usan el mismo nombre para la columna o columnas de unión. Toma una lista separada por comas de la nombres de columna compartidos y formularios una condición de unión que incluye un comparación de igualdad para cada uno. Por ejemplo, uniendo T1 y T2 con EL USO DE (a, b) produce la condición de unión EN T1.a = T2.a Y T1.b = T2.b.

Además, la salida de JOIN USANDO suprime columnas redundantes: no es necesario imprimir las dos columnas coincidentes, puesto que deben tener valores iguales. Mientras que JOIN ON produce todas las columnas de T1 seguido por todas las columnas de T2, UNIR USANDO produce una columna de salida para cada de los pares de columnas listados (en el orden listado), seguido de cualquier columnas restantes de T1, seguidas de las columnas restantes de T2.

 9
Author: Robert Rocha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-11 19:20:00

Para aquellos que experimentan con esto en phpMyAdmin, solo una palabra:

PhpMyAdmin parece tener algunos problemas con USING. Para el registro esto es phpMyAdmin ejecutar en Linux Mint, versión: "4.5.4. 1deb2ubuntu2", Servidor de base de datos: "10.2.14-MariaDB-10.2.14+maria~xenial - mariadb.org binary distribution".

He ejecutado SELECT comandos usando JOIN y USING tanto en phpMyAdmin como en Terminal (línea de comandos), y los de phpMyAdmin producen algunas respuestas desconcertantes:

1) a LIMIT la cláusula al final parece ser ignorada.
2) el número supuesto de filas según se informa en la parte superior de la página con los resultados a veces es incorrecto: por ejemplo, se devuelven 4, pero en la parte superior dice "Mostrando filas 0 - 24 (2503 en total, La consulta tomó 0.0018 segundos.)"

Iniciar sesión en mysql normalmente y ejecutar las mismas consultas no produce estos errores. Estos errores tampoco ocurren cuando se ejecuta la misma consulta en phpMyAdmin usando JOIN ... ON .... Presumiblemente un error phpMyAdmin.

 0
Author: mike rodent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-07 21:10:58