Filtrar tabla antes de aplicar la combinación izquierda

82

Tengo 2 tablas, quiero filtrar la 1 tabla antes de que las 2 tablas se unan.

Tabla de clientes:

   ╔══════════╦═══════╗
   ║ Customer ║ State ║
   ╠══════════╬═══════╣
   ║ A        ║ S     ║
   ║ B        ║ V     ║
   ║ C        ║ L     ║
   ╚══════════╩═══════╝

Tabla de entrada:

   ╔══════════╦═══════╦══════════╗
   ║ Customer ║ Entry ║ Category ║
   ╠══════════╬═══════╬══════════╣
   ║ A        ║  5575 ║ D        ║
   ║ A        ║  6532 ║ C        ║
   ║ A        ║  3215 ║ D        ║
   ║ A        ║  5645 ║ M        ║
   ║ B        ║  3331 ║ A        ║
   ║ B        ║  4445 ║ D        ║
   ╚══════════╩═══════╩══════════╝

Quiero unirme a la izquierda para obtener todos los registros de la tabla Cliente independientemente de si hay registros relacionados en la tabla Entrada. Sin embargo, quiero filtrar por categoría D en la tabla de entrada antes de la combinación .

Resultados deseados:

   ╔══════════╦═══════╦═══════╗
   ║ Customer ║ State ║ Entry ║
   ╠══════════╬═══════╬═══════╣
   ║ A        ║ S     ║  5575 ║
   ║ A        ║ S     ║  3215 ║
   ║ B        ║ V     ║  4445 ║
   ║ C        ║ L     ║  NULL ║
   ╚══════════╩═══════╩═══════╝

Si tuviera que hacer la siguiente consulta:

   SELECT Customer.Customer, Customer.State, Entry.Entry
   FROM Customer
   LEFT JOIN Entry
   ON Customer.Customer=Entry.Customer
   WHERE Entry.Category='D'

Esto filtraría el último registro.

Así que quiero todas las filas de la tabla de la izquierda y unirlas a la tabla de entrada filtrada en la categoría D.

Gracias a cualquier ayuda de antemano !!

Tom Jenkin
fuente
Vea este enlace - sqlbenjamin.wordpress.com/2017/12/23/…
MasterJoe

Respuestas:

115

Necesita mover el WHEREfiltro a la JOINcondición:

SELECT c.Customer, c.State, e.Entry
FROM Customer c
LEFT JOIN Entry e
   ON c.Customer=e.Customer
   AND e.Category='D'

Ver SQL Fiddle con demostración

Taryn
fuente
1
¡Vaya, eres rápido y eficiente! Esto funciona, ¡gracias por la ayuda!
Tom Jenkin
8
@TomJenkin gracias, por cierto, publicaste una fantástica primera pregunta en el sitio. Muchos detalles, etc.
Taryn
Gracias - Creo que voy a disfrutar usando este sitio, espero poder contribuir como tú algún día: D
Tom Jenkin
2
@bluefeet pero ambos planes de ejecución son iguales, ¿no?
Alex Zhukovskiy
1
Aplicar el filtrado en una tabla de la que depende la combinación antes de unirse si las condiciones where apuntan a la primera tabla. Al menos en algunas de mis pruebas vi eso. Publiqué ese comentario en respuesta al comentario de Alex.
Áxel Costas Pena
28

También puedes hacer:

SELECT c.Customer, c.State, e.Entry
FROM Customer AS c
LEFT JOIN (SELECT * FROM Entry WHERE Category='D') AS e
ON c.Customer=e.Customer

SQL Fiddle aquí

Jeff Rosenberg
fuente
3
@TomJenkin Perdón por la respuesta tardía, he estado lejos de la computadora todo este tiempo. Sin embargo, por curiosidad, ejecuté ambos y verifiqué los planes de ejecución. Los planes de ejecución son casi idénticos, pero en la medida en que cualquiera sea mejor, parece que es la versión de Bluefeet.
Jeff Rosenberg
Genial, esto me inspiró a arreglar mi caso.
sivann
1

O...

SELECT c.Customer, c.State, e.Entry
FROM Customer c
LEFT JOIN Entry e
   ON c.Customer=e.Customer
WHERE e.Category IS NULL or e.Category='D'
cz
fuente
En SQL JOIN, la condición se ejecuta antes de WHERE. Entonces, en la solución sugerida, se une la tabla completa y se filtra el resultado, lo que puede ser bastante costoso cuando se trata de tablas grandes. La condición de filtro deseada debe ser parte de la condición JOIN como se sugiere en otras respuestas
Omley
@Omley Creo que estás confundido acerca de cómo funciona SQL. SQL es declarativo , no procedimental . El orden de las palabras en la consulta no afecta el orden de las operaciones . Eso depende del motor. Podemos ver de una manera simple EXPLAINque MySql en realidad lo hace marginalmente mejor en la optimización de esta consulta que la de la respuesta de Taryn, aunque esto ciertamente será más suerte que administración y lo contrario puede ser cierto para otro motor.
cz