¿Hay algún problema con las combinaciones que no usan la palabra clave JOIN en SQL o MySQL?

StackOverflow https://stackoverflow.com/questions/128965

  •  02-07-2019
  •  | 
  •  

Pregunta

Cuando comencé a escribir consultas en la base de datos, todavía no conocía la palabra clave JOIN y, naturalmente, simplemente extendí lo que ya sabía y escribí consultas como esta:

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 un INNER JOIN, encuentro todas estas consultas en mi código y me pregunto si debería volver a escribirlas. ¿Hay algo maloliente en ellos o están bien?


EDITAR:

Resumen de mi respuesta : No hay nada de malo en esta consulta PERO usar las palabras clave 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 utilizaré las palabras clave en el futuro.

¡GRACIAS por sus respuestas!

¿Fue útil?

Solución

El filtrado se une únicamente con 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 ejecutarán esta consulta literalmente, primero tomando el producto cartesiano del personas y companies tablas y luego filtrado por aquellos que tienen campos coincidentes companyID y id . Si bien el producto sin restricciones 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. Por lo tanto:

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 puede mirar la cláusula ON y usarla para calcular directamente la JOIN completamente restringida, en lugar de comenzar con < em> todo y luego limitando. Esto es más rápido de calcular (especialmente con grandes conjuntos de datos y / o uniones de muchas tablas) y requiere menos memoria.

Modifico cada consulta que veo que usa la coma "código" JOIN " sintaxis. 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.

Otros consejos

Las INNER JOIN más detalladas, la IUTER OUTER JOIN, la DERECHA OUTER JOIN, la 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 cuál es la intención con la unión.

En SQL Server siempre hay planes de consulta para verificar, 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 omitiré el plan para la variable de tabla que crea, el plan para ambas consultas es idéntico:

 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]=@TABLE_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]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)

Entonces, respuesta corta: ¿no es necesario volver a escribir, a menos que pase mucho tiempo intentando leerlos cada vez que los mantiene?

Es más una elección de sintaxis. Prefiero agrupar mis condiciones de unión con mis uniones, por lo tanto, 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)

No hay nada malo con la sintaxis en su ejemplo. La sintaxis 'INNER JOIN' generalmente se denomina sintaxis 'ANSI', y vino después del estilo ilustrado en su ejemplo. Existe para aclarar el tipo / dirección / constituyentes de la unión, pero generalmente no es funcionalmente diferente de lo que tiene.

El soporte para 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.

En general:

Use la palabra clave JOIN para vincular (es decir, " unirse ") claves principales y claves externas.

Use la cláusula WHERE para limitar su conjunto de resultados a solo los registros que le interesen.

El único problema que puede surgir es cuando intentas mezclar el antiguo "estilo de coma". unirse con combinaciones SQL-92 en la misma consulta, por ejemplo, si necesita una combinación interna y otra 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 combinación de comas. Entonces la referencia a " a " en la cláusula ON da un error, porque el nombre de correlación aún no se ha definido ya que se está evaluando esa cláusula ON. Es un error muy confuso de obtener.

La solución es no mezclar los dos estilos de combinaciones. Puede continuar usando el estilo de coma en su código anterior, pero si escribe una nueva consulta, 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;

Otra cosa a tener en cuenta en la antigua sintaxis de unión es que es muy fácil obtener una unión cartesion por accidente ya que no hay una cláusula. Si la palabra clave Distinct está en la consulta y usa las combinaciones de estilo antiguo, conviértala en una combinación estándar ANSI y vea si aún necesita la distinción. Si está arreglando uniones de cartesión accidental de esta manera, puede mejorar enormemente el rendimiento al reescribir para especificar los campos de unión y unión.

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

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

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top