Condición dentro de JOIN o WHERE

Resuelto Steve Dignan asked hace 15 años • 10 respuestas

¿Existe alguna diferencia (rendimiento, mejores prácticas, etc.) entre poner una condición en la cláusula JOIN y la cláusula WHERE?

Por ejemplo...

-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'

-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'

¿Cuál prefieres (y quizás por qué)?

Steve Dignan avatar Jun 19 '09 23:06 Steve Dignan
Aceptado

El álgebra relacional permite la intercambiabilidad de los predicados en la WHEREcláusula y el INNER JOIN, por lo que incluso INNER JOINlas consultas con WHEREcláusulas pueden tener los predicados reorganizados por el optimizador para que ya puedan ser excluidos durante el JOINproceso.

Te recomiendo que escribas las consultas de la forma más legible posible.

A veces, esto incluye hacer que las listas de INNER JOINcriterios de filtrado sean relativamente "incompletas" y poner algunos de los criterios simplemente WHEREpara 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

Escribir:

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

Cade Roux avatar Jun 19 '2009 17:06 Cade Roux

Para las uniones internas realmente no he notado una diferencia (pero como ocurre con todos los ajustes de rendimiento, debe comparar con su base de datos según sus condiciones).

Sin embargo, el lugar donde se coloca la condición hace una gran diferencia si se utilizan combinaciones izquierda o derecha. Por ejemplo, considere estas dos consultas:

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderDate >'20090515'

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'

El primero le proporcionará sólo aquellos registros que tengan un pedido con fecha posterior al 15 de mayo de 2009, convirtiendo así la combinación izquierda en una combinación interna.

El segundo proporcionará esos registros más los clientes sin pedidos. El conjunto de resultados es muy diferente dependiendo de dónde coloques la condición. (Seleccionar * es solo para fines de ejemplo; por supuesto, no debe usar esto en el código de producción).

La excepción a esto es cuando desea ver solo los registros de una tabla pero no de la otra. Luego usa la cláusula donde para la condición, no para la unión.

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderID is null
HLGEM avatar Jun 19 '2009 18:06 HLGEM

La mayoría de los productos RDBMS optimizarán ambas consultas de manera idéntica. En "SQL Performance Tuning" de Peter Gulutzan y Trudy Pelzer, probaron varias marcas de RDBMS y no encontraron diferencias en el rendimiento.

Prefiero mantener las condiciones de unión separadas de las condiciones de restricción de consultas.

Si lo utiliza, OUTER JOINa veces es necesario poner condiciones en la cláusula de unión.

Bill Karwin avatar Jun 19 '2009 16:06 Bill Karwin