
Optimizando una consulta SQL que utiliza RIGHT JOIN: ejemplo práctico
Tiempo total: 0 días con 10:34:33 hrs
La función de RIGHT JOIN es devolver todos los registros de la tabla a la derecha, si existe alguna coincidencia devolverá los valores de la tabla a la izquierda, caso contrario devolverá NULL en vez de dichos valores.

Optimizando una atrocidad
Dada la siguiente consulta SQL, considere el problema: la consulta tarda tiempo infinito en ejecutarse.
SELECT c.tipo, SUM(cp.cantidad) as cantidad, SUM(IF(DATE(p.fecha) = '2019-03-20', cp.cantidad, 0)) as cantidad_hoy FROM contrato_pagado cp RIGHT JOIN contrato_no_pagado cnp ON cp.contrato_no_pagado= cnp.id RIGHT JOIN contrato c ON cnp.contrato = c.id RIGHT JOIN pago p ON cp.pago = p.id WHERE AND DATE(p.fecha) >= '2019-03-18' AND DATE(p.fecha) <= '2019-03-24' GROUP BY c.tipo
En una tabla de unos cuantos registros, dicha consulta se ejecutará sin problemas, pero que sucede cuando existen muchos registros? Tienes idea de porque el programador utilizo RIGHT JOIN en la consulta? No sabes si el RIGHT JOIN está para lograr hacer algún calculo? En general, de qué manera puedo optimizar una consulta?
Simplificación de consulta
El primer paso para optimizar una consulta es simplificándola, nos quedará así:
- cp
- cnp RIGHT JOIN cp.cnp = cnp.id
- c RIGHT JOIN cnp.c = c.id
- p RIGHT JOIN cp.p = p.id
WHERE 2019-03-18 < p.f < 2019-03-24
Aquí observamos cómo están relacionadas las tablas. Con esto, podemos armar un gráfico simple para aclarar más lo que el programador estaba haciendo:
Con el gráfico anterior, tenemos que preguntarnos: que campos se muestran en el SELECT?
La consulta gira en torno a la sumatoria de los valores CP, así que es innecesario obtener registros de CNP o de P en donde los valores de CP sean NULL. En base a esto, hagamos el gráfico real de los datos que nos interesan:

Observamos que no es necesario utilizar los RIGHT JOIN: los datos a la derecha no nos interesan en ningún caso. El SQL optimizado debería de ser:
SELECT c.tipo, SUM(cp.cantidad) as cantidad, SUM(IF(DATE(p.fecha) = '2019-03-20', cp.cantidad, 0)) as cantidad_hoy FROM contrato_pagado cp JOIN contrato_no_pagado cnp ON cp.contrato_no_pagado= cnp.id JOIN contrato c ON cnp.contrato = c.id JOIN pago p ON cp.pago = p.id WHERE AND DATE(p.fecha) >= '2019-03-18' AND DATE(p.fecha) <= '2019-03-24' GROUP BY c.tipo
Con solo eliminar los RIGH JOIN por un simple JOIN, pasamos de un tiempo infinito a milésimas de segundo.