Cláusula INNER JOIN ON vs WHERE


Para simplificar, supongamos que todos los campos relevantes son NOT NULL.

Puedes hacer:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1, table2
WHERE
    table1.foreignkey = table2.primarykey
    AND (some other conditions)

O bien:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1 INNER JOIN table2
    ON table1.foreignkey = table2.primarykey
WHERE
    (some other conditions)

¿Funcionan estos dos de la misma manera en MySQL?

Author: Uwe Keim, 2009-06-19

10 answers

INNER JOIN es la sintaxis ANSI que debe usar.

Generalmente se considera más legible, especialmente cuando se une a muchas tablas.

También se puede reemplazar fácilmente con un OUTER JOIN siempre que surja una necesidad.

La sintaxis WHERE está más orientada a modelos relacionales.

Un resultado de dos tablas JOIN ed es un producto cartesiano de las tablas a las que se aplica un filtro que selecciona solo aquellas filas con columnas de unión coincidentes.

Es más fácil ver esto con la sintaxis WHERE.

En cuanto a su ejemplo, en MySQL (y en SQL en general) estas dos consultas son sinónimos.

También tenga en cuenta que MySQL también tiene una cláusula STRAIGHT_JOIN.

Usando esta cláusula, puede controlar el orden JOIN: qué tabla se escanea en el bucle exterior y cuál está en el bucle interior.

No puede controlar esto en MySQL usando la sintaxis WHERE.

 622
Author: Quassnoi,
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
2017-11-19 16:28:17

Otros han señalado que LA UNIÓN INTERNA ayuda a la legibilidad humana, y esa es una prioridad máxima; estoy de acuerdo. Permítanme tratar de explicar por qué la sintaxis de unión es más legible.

Una consulta de SELECCIÓN básica es la siguiente:

SELECT stuff
FROM tables
WHERE conditions

La cláusula SELECT nos dice ¿qué estamos recibiendo de vuelta; la cláusula FROM nos dice donde lo estamos recibiendo, y la cláusula where nos dice que que estamos recibiendo.

JOIN es una declaración sobre las tablas, cómo están enlazadas juntos (conceptualmente, en realidad, en una sola tabla). Todos los elementos de consulta que controlan las tablas - de donde obtenemos las cosas - semánticamente pertenecen a la cláusula FROM (y por supuesto, ahí es donde van los elementos JOIN). Poner joining-elements en la cláusula WHERE combina which y where-from; es por eso que se prefiere la sintaxis JOIN.

 149
Author: Carl Manaster,
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
2009-06-19 16:30:59

Aplicación de declaraciones condicionales en ON / WHERE

Aquí he explicado sobre los pasos lógicos de procesamiento de consultas.


Referencia: Dentro de Microsoft ® SQL Server ™ 2005 Consulta T-SQL
Editor: Microsoft Press
Fecha de publicación: 07 de marzo de 2006
Imprimir ISBN-10: 0-7356-2313-9
Imprimir ISBN-13: 978-0-7356-2313-2
Páginas: 640

Dentro de Microsoft® SQL Server™ 2005 T-SQL Querying

(8)  SELECT (9) DISTINCT (11) TOP <top_specification> <select_list>
(1)  FROM <left_table>
(3)       <join_type> JOIN <right_table>
(2)       ON <join_condition>
(4)  WHERE <where_condition>
(5)  GROUP BY <group_by_list>
(6)  WITH {CUBE | ROLLUP}
(7)  HAVING <having_condition>
(10) ORDER BY <order_by_list>

El primer notable aspecto de SQL que es diferente de otros lenguajes de programación es el orden en el que se procesa el código. En la mayoría de los lenguajes de programación, el código se procesa en el orden en que se escribe. En SQL, la primera cláusula que se procesa es la cláusula FROM, mientras que la cláusula SELECT, que aparece primero, se procesa casi por última vez.

Cada paso genera una tabla virtual que se utiliza como entrada para el siguiente paso. Estas tablas virtuales no están disponibles para la persona que llama (cliente aplicación o consulta externa). Solo la tabla generada por el paso final se devuelve al llamador. Si una cláusula determinada no se especifica en una consulta, el paso correspondiente simplemente se omite.

Breve Descripción de las Fases de Procesamiento Lógico de Consultas

No se preocupe demasiado si la descripción de los pasos no parece tener mucho sentido por ahora. Estos se proporcionan como referencia. Las secciones que vienen después del ejemplo del escenario cubrirán los pasos en mucho más detalle.

  1. FROM: Se realiza un producto cartesiano (combinación cruzada) entre las dos primeras tablas de la cláusula FROM y, como resultado, se genera la tabla virtual VT1.

  2. ON: El filtro ON se aplica a VT1. Solo las filas para las que <join_condition> es TRUE se insertan en VT2.

  3. OUTER (join): Si se especifica una UNIÓN EXTERNA (a diferencia de una UNIÓN CRUZADA o una UNIÓN INTERNA), las filas de la tabla o tablas conservadas para las que no se encontró una coincidencia se agregan a las filas de VT2 como filas externas, generando VT3. Si aparecen más de dos tablas en la cláusula FROM, los pasos del 1 al 3 se aplican repetidamente entre el resultado de la última combinación y la siguiente tabla en la cláusula FROM hasta que se procesen todas las tablas.

  4. DÓNDE: El filtro DÓNDE se aplica a VT3. Solo las filas para las que <where_condition> es TRUE se insertan en VT4.

  5. AGRUPAR POR: Las filas de VT4 se organizan en grupos según la lista de columnas especificada en el GRUPO POR clausula. Se genera VT5.

  6. CUBE / ROLLUP: Se agregan supergrupos (grupos de grupos) a las filas de VT5, generando VT6.

  7. HAVING: El filtro HAVING se aplica a VT6. Solo los grupos para los que <having_condition> es TRUE se insertan en VT7.

  8. SELECCIONAR: La lista de selección se procesa, generando VT8.

  9. DISTINTO: Las filas duplicadas se eliminan de VT8. Se genera VT9.

  10. ORDENAR POR: Las filas de VT9 están ordenadas según la lista de columnas especificada en la cláusula ORDER BY. Se genera un cursor (VC10).

  11. TOP: El número o porcentaje especificado de filas se selecciona desde el principio de VC10. La tabla VT11 se genera y se devuelve al autor de la llamada.



Por lo tanto, (INNER JOIN) ON filtrará los datos (el recuento de datos de VT se reducirá aquí mismo) antes de aplicar la cláusula WHERE. Las condiciones de unión posteriores se ejecutarán con filtered datos que mejoran el rendimiento. Después de eso, solo la condición WHERE aplicará las condiciones de filtro.

(Aplicar sentencias condicionales en ON / WHERE no hará mucha diferencia en pocos casos. Esto depende de cuántas tablas se han unido y el número de filas disponibles en cada tabla de unión)

 115
Author: rafidheen,
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-09-28 18:38:37

La sintaxis ANSI de unión implícita es más antigua, menos obvia y no recomendada.

Además, el álgebra relacional permite la intercambiabilidad de los predicados en la cláusula WHERE y la INNER JOIN, por lo que incluso las consultas INNER JOIN con cláusulas WHERE pueden tener los predicados reorganizados por el optimizador.

Te recomiendo que escribas las consultas de la manera más fácil posible.

A veces esto incluye hacer el INNER JOIN relativamente "incompleto" y poner algunos de los criterios en el WHERE simplemente para hacer que las listas de criterios de filtrado sean más fáciles de mantener.

Por ejemplo, en lugar de:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

Escribe:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

, Pero depende, por supuesto.

 55
Author: Cade Roux,
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
2009-06-19 16:23:45

Las uniones implícitas (que es como se conoce a su primera consulta) se vuelven mucho más confusas, difíciles de leer y difíciles de mantener una vez que necesita comenzar a agregar más tablas a su consulta. Imagine hacer la misma consulta y tipo de unión en cuatro o cinco tablas diferentes ... es una pesadilla.

Usar una combinación explícita (su segundo ejemplo) es mucho más legible y fácil de mantener.

 26
Author: matt b,
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
2009-06-19 16:19:14

También señalaré que el uso de la sintaxis más antigua está más sujeto a errores. Si usa uniones internas sin una cláusula ON, obtendrá un error de sintaxis. Si utiliza la sintaxis anterior y olvida una de las condiciones de unión en la cláusula where, obtendrá una combinación cruzada. Los desarrolladores a menudo arreglan esto agregando la palabra clave distinct (en lugar de arreglar la combinación porque todavía no se dan cuenta de que la combinación en sí está rota), lo que puede parecer que cura el problema, pero ralentizará la consulta considerablemente.

Además para el mantenimiento si tiene una combinación cruzada en la sintaxis antigua, ¿cómo sabrá el mantenedor si pretendía tener una (hay situaciones en las que se necesitan combinaciones cruzadas) o si fue un accidente que debería arreglarse?

Déjame dirigirte a esta pregunta para ver por qué la sintaxis implícita es mala si usas combinaciones izquierdas. Sybase * = al estándar Ansi con 2 tablas externas diferentes para la misma tabla interna

Plus (diatriba personal aquí), el estándar el uso de las uniones explícitas tiene más de 20 años, lo que significa que la sintaxis de unión implícita ha estado desactualizada durante esos 20 años. ¿Escribiría código de aplicación utilizando una sintaxis que ha estado desactualizada durante 20 años? ¿Por qué quieres escribir código de base de datos que es?

 22
Author: HLGEM,
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
2017-05-23 12:02:50

Tienen un significado diferente legible por el ser humano.

Sin embargo, dependiendo del optimizador de consultas, pueden tener el mismo significado para la máquina.

Siempre debe codificar para que sea legible.

Es decir, si esta es una relación incorporada, use la combinación explícita. si coincide con datos débilmente relacionados, utilice la cláusula where.

 12
Author: John Gietzen,
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
2010-04-15 22:04:49

El estándar SQL:2003 cambió algunas reglas de precedencia para que una sentencia JOIN tenga prioridad sobre una unión "coma". Esto realmente puede cambiar los resultados de su consulta dependiendo de cómo está configurado. Esto causa algunos problemas para algunas personas cuando MySQL 5.0.12 cambió a adherirse al estándar.

Así que en tu ejemplo, tus consultas funcionarían igual. Pero si agregaste una tercera tabla: SELECCIONAR ... DESDE table1, table2 UNIRSE A table3 EN ... DONDE ...

Antes de MySQL 5.0.12, table1 y la tabla 2 se uniría primero, luego la tabla 3. Ahora (5.0.12 y en adelante), table2 y table3 se unen primero, luego table1. No siempre cambia los resultados, pero puede y puede que ni siquiera te des cuenta.

Ya no uso la sintaxis "coma", optando por su segundo ejemplo. Es mucho más legible de todos modos, las condiciones de unión son con las uniones, no separadas en una sección de consulta separada.

 10
Author: Brent Baisley,
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
2009-06-19 17:28:56

Sé que estás hablando de MySQL, pero de todos modos: En Oracle 9, las uniones explícitas y las uniones implícitas generarían diferentes planes de ejecución. AFAIK que se ha resuelto en Oracle 10+: ya no hay tal diferencia.

 4
Author: João Marcus,
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
2009-06-19 17:03:42

La sintaxis ANSI join es definitivamente más portátil.

Estoy pasando por una actualización de Microsoft SQL Server, y también me gustaría mencionar que la sintaxis =* y *= para las uniones externas en SQL Server no es compatible (sin modo de compatibilidad) para 2005 sql server y posteriores.

 1
Author: Benzo,
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
2009-06-19 16:50:12