2008-09-24 6 views
40

Cuando empecé a escribir consultas de bases de datos no sabía la palabra clave JOIN y, naturalmente, sin embargo, yo sólo extendí lo que ya sabía y escribió consultas como esta:¿Hay algún problema con las combinaciones que no utilizan la palabra clave JOIN en SQL o MySQL?

SELECT a.someRow, b.someRow 
FROM tableA AS a, tableB AS b 
WHERE a.ID=b.ID AND b.ID= $someVar 

Ahora que sé que esto es lo mismo que una INNER JOIN Encuentro todas estas consultas en mi código y me pregunto si debería volver a escribirlas. ¿Hay algo de mal olor en ellos o están bien?


EDIT:

Mi resumen respuesta: No hay nada malo con esta consulta pero usando las palabras clave más probablemente hará que el código sea más legible/mantenible.

Mi conclusión: No cambiaré mis consultas anteriores pero corregiré mi estilo de escritura y usaré las palabras clave en el futuro.

¡GRACIAS por sus respuestas!

+0

El estándar ANSI SQL cambia con el tiempo. La capacidad de expresar uniones externas es anterior a la introducción de la sintaxis de la cláusula JOIN. La sintaxis de unión proporciona, de paso, una oportunidad para indexar y unir sugerencias. –

+2

Su resumen es incorrecto, por lo que su conclusión es mala. La diferencia en las consultas es que la siguiente respuesta llevará a cabo la cláusula where en un subconjunto de datos mucho más pequeño. El rendimiento es mucho mayor y, por lo tanto, debería considerar reescribir las consultas utilizando combinaciones internas donde pueda. – achinda99

+0

La respuesta aceptada por DanielSpiewak es simplemente incorrecta. Están fantaseando con la implementación. Las optimizaciones para las uniones no externas de a, en y donde * sintaxis * son triviales. Para MySQL, vea específicamente la documentación oficial re [join optimization] (https://dev.mysql.com/doc/refman/5.7/en/left-join-optimization.htm) y otros aspectos de la optimización). – philipxy

Respuesta

34

Filtrado de combinaciones utilizar únicamente WHERE puede ser extremadamente ineficiente en algunos escenarios comunes. Por ejemplo:

SELECT * FROM people p, companies c 
    WHERE p.companyID = c.id AND p.firstName = 'Daniel' 

La mayoría de las bases de datos se ejecute esta consulta, literalmente, tomar la primera Cartesian product de los people y companies tablas y luego filtrado por los que hayan juego companyID y id campos. Si bien el producto no restringido no existe en ningún lugar sino en la memoria y solo por un momento, su cálculo lleva algún tiempo.

Un mejor enfoque es agrupar las restricciones con JOIN s cuando sea relevante. Esto no solo es subjetivamente más fácil de leer sino también mucho más eficiente. De esta manera:

SELECT * FROM people p JOIN companies c ON p.companyID = c.id 
    WHERE p.firstName = 'Daniel' 

Es un poco más largo, pero la base de datos es capaz de mirar a la cláusula ON y utilizarla para calcular la JOIN totalmente constreñida-directamente, en lugar de comenzar con todo y luego limitar hacia abajo. Esto es más rápido de calcular (especialmente con grandes conjuntos de datos y/o combinaciones de varias tablas) y requiere menos memoria.

Cambio cada consulta que veo que utiliza la sintaxis "coma JOIN". En mi opinión, el único propósito de su existencia es la concisión. Teniendo en cuenta el impacto en el rendimiento, no creo que esta sea una razón convincente.

+11

¿Puede proporcionar ejemplos de sistemas de bases de datos que hacen productos cartesianos en la sintaxis de unión anterior? La sintaxis anterior es lo suficientemente común como para pensar que la mayoría de los optimizadores de DBMS sabrían que no deben hacer esto. –

+1

También me adhiero a lo que Michael escribió. Definitivamente hay una necesidad de [citación necesitada] dentro de StackOverflow. –

+5

Pídale a su DBMS que le explique ambas declaraciones. Un buen sistema tendrá la sintaxis anterior de la combinación de SQL y SQL 1992 para realizar operaciones equivalentes. – dlamblin

4

No hay ningún problema con la sintaxis en su ejemplo. La sintaxis 'INNER JOIN' generalmente se denomina sintaxis 'ANSI' y viene después del estilo ilustrado en su ejemplo. Existe para aclarar el tipo/dirección/componentes de la unión, pero generalmente no es funcionalmente diferente de lo que tienes.

El soporte para las uniones 'ANSI' es por plataforma de base de datos, pero es más o menos universal en estos días.

Como nota al margen, una adición con la sintaxis 'ANSI' fue 'FULL OUTER JOIN' o 'FULL JOIN'.

Espero que esto ayude.

3

Evito combinaciones implícitas; cuando la consulta es realmente grande, hacen que el código sea difícil de descifrar

Con combinaciones explícitas y buen formato, el código es más legible y comprensible sin necesidad de comentarios.

+0

+1 Sí. Y un predicado de combinación faltante es más fácil de detectar. La sintaxis JOIN hace que una declaración SQL que se ve mal se equivoque, es más obvio que hay un problema. – spencer7593

5

Es más una opción de sintaxis. Yo prefiero la agrupación de mis condiciones de unión con mi une, por lo tanto, yo uso la sintaxis INNER JOIN

SELECT a.someRow, b.someRow 
FROM tableA AS a 
INNER JOIN tableB AS b 
    ON a.ID = b.ID 
WHERE b.ID = ? 

(? Ser un marcador de posición)

10

Cuanto más detallado INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN son de la sintaxis ANSI SQL/92 para la unión. Para mí, esta verbosidad hace que la unión sea más clara para el desarrollador/DBA de lo que es la intención con la unión.

+3

Y hace que sea más fácil detectar un predicado de unión faltante. La sintaxis JOIN hace que una declaración incorrecta se vea mal. Un predicado de combinación faltante es más difícil de detectar en la sintaxis de estilo anterior. – spencer7593

6

En SQL Server siempre hay planes de consulta para comprobar, una salida de texto se puede hacer de la siguiente manera:

SET SHOWPLAN_ALL ON 
GO 

DECLARE @TABLE_A TABLE 
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    Data VARCHAR(10) NOT NULL 
) 
INSERT INTO @TABLE_A 
SELECT 'ABC' UNION 
SELECT 'DEF' UNION 
SELECT 'GHI' UNION 
SELECT 'JKL' 

DECLARE @TABLE_B TABLE 
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    Data VARCHAR(10) NOT NULL 
) 
INSERT INTO @TABLE_B 
SELECT 'ABC' UNION 
SELECT 'DEF' UNION 
SELECT 'GHI' UNION 
SELECT 'JKL' 

SELECT A.Data, B.Data 
FROM 
    @TABLE_A AS A, @TABLE_B AS B 
WHERE 
    A.ID = B.ID 

SELECT A.Data, B.Data 
FROM 
    @TABLE_A AS A 
    INNER JOIN @TABLE_B AS B ON A.ID = B.ID 

Ahora voy a omitir el plan de la tabla crea variable, el plan para ambas consultas es idéntica sin embargo:

SELECT A.Data, B.Data FROM @TABLE_A AS A, @TABLE_B AS B WHERE A.ID = B.ID 
    |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID])) 
     |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A])) 
     |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID][email protected]_A.[ID] as [A].[ID]) ORDERED FORWARD) 
SELECT A.Data, B.Data FROM @TABLE_A AS A INNER JOIN @TABLE_B AS B ON A.ID = B.ID 
    |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID])) 
     |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A])) 
     |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID][email protected]_A.[ID] as [A].[ID]) ORDERED FORWARD) 

Así, respuesta corta - No hay necesidad de volver a escribir, a menos que pasar mucho tiempo tratando de leerlas cada vez que mantenerlas?

2

También depende de si solo está haciendo uniones internas de esta manera o también combinaciones externas. Por ejemplo, la sintaxis de MS SQL Server para uniones externas en la cláusula WHERE (= * y * =) puede dar resultados diferentes a la sintaxis OUTER JOIN y ya no es compatible (http://msdn.microsoft.com/en-us/library/ms178653(SQL.90).aspx) en SQL Server 2005.

4

En general:

utilizar la palabra clave JOIN para enlazar (es decir, "unir".) Las claves principales y claves externas.

uso de la cláusula WHERE para limitar el conjunto de resultados que sólo los registros que están interesados ​​en.

4

El único problema que puede surgir es cuando se trata de mezclar el viejo "estilo coma" unirse con SQL-92 se une a la misma consulta, por ejemplo, si necesita una combinación interna y otra combinación externa.

SELECT * 
FROM table1 AS a, table2 AS b 
LEFT OUTER JOIN table3 AS c ON a.column1 = c.column1 
WHERE a.column2 = b.column2; 

El problema es que los estándares SQL recientes dicen que JOIN se evalúa antes de la coma. Entonces, la referencia a "a" en la cláusula ON arroja un error, porque el nombre de la correlación aún no se ha definido como esa cláusula ON que se está evaluando. Este es un error muy confuso de obtener.

La solución es no mezclar los dos estilos de combinaciones. Puede seguir utilizando el estilo de coma en su código anterior, pero si escribe una consulta nueva, convierta todas las combinaciones al estilo SQL-92.

SELECT * 
FROM table1 AS a 
INNER JOIN table2 AS b ON a.column2 = b.column2 
LEFT OUTER JOIN table3 AS c ON a.column1 = c.column1; 
3

Otra cosa a tener en cuenta en la antigua sintaxis de combinación es que es muy fácil de conseguir un cartesion unen por accidente ya que no está en la cláusula. Si la palabra clave Distinct está en la consulta y utiliza las combinaciones de estilo antiguo, conviértala a una unión estándar ANSI y vea si aún necesita la distinción. Si está corrigiendo combinaciones de cajas accidentales de esta manera, puede mejorar enormemente el rendimiento volviendo a escribir para especificar los campos de unión y unión.

Cuestiones relacionadas