SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.
Siempre que uno se dispone a programar un SQL Query, trata de hacerlo lo más sencillo que se pueda. Claro, esto nos enseñan en la universidad, pero una cosa es la teoría y otra es, la realidad. Esto desde un punto de vista algo ligero puede parecer ideal. Sin embargo, muchas veces nos olvidamos de tomar encuentra una variable muy pero muy importante como lo es el rendimiento. La idea no es programar una consulta con tal que nos devuelva el resultado deseado asi de simple, sino que, por encima de vuestros facilitismos académicos debe predominar la calidad y rendimiento de un SQL Query .
Es así que, mediante este post se pretende demostrar que lo "fácil" tiene un costo de rendimiento, y aveces esto suele ser muy elevado. Digo esto porque mucho se escucha decir que un SQL Self-Join se usa para simplificar un SQL Nested-Join, y que bla.. bla... bla.. y que en muchos sitios se recomienda, pero como ya dije y vuelvo a decir (las veces que sean necesarias), todo esto tiene un costo de rendimiento que se incrementa de acuerdo al tipo de data y la cantidad de la misma que se consulte.
En esta demostración he tomado por conveniente confrontar los resultados de dos tipos de consultas muy conocidas, y antes comentada, como son los SQL Self-Join y SQL Nested-Join. Como sabéis, un self-join es un SQL Join que une una tabla con ella misma. Esto es posible gracias al uso de alias para cada tabla consiguiendo de esta manera una instancia de cada tabla por separado para poder trabajar sobre ellas. Esto es de gran ayuda pero no te olvides del rendimiento. A continuación unos ejemplos de este tipo de query :
SQL Self-Join 01
SELECT E1.EMPLOYEENAME AS EMPLOYEE,
E2.EMPLOYEENAME AS MANAGER
FROM EMPLOYEES AS E1
INNER JOIN EMPLOYEES AS E2
ON E1.MANAGERID = E2.EMPLOYEEID
SQL Self-Join 02
USE ADVENTUREWORKS
GO
SELECT DISTINCT PV1.PRODUCTID,
PV1.VENDORID
FROM PURCHASING.PRODUCTVENDOR PV1
INNER JOIN PURCHASING.PRODUCTVENDOR PV2
ON PV1.PRODUCTID = PV2.PRODUCTID
AND PV1.VENDORID <> PV2.VENDORID
ORDER BY PV1.PRODUCTID
Por otra parte, debe quedar claro que un SQL Nested-Join es un tipo de consulta anidada como por ejemplo:
SELECT *
FROM PERSON.CONTACT C1
WHERE C1.FIRSTNAME IN (SELECT FIRSTNAME
FROM PERSON.CONTACT
WHERE MIDDLENAME = 'D'
AND LASTNAME = 'Cox')
Ahora que ya se sabe que es un Self-Join y un Nested-Join, pasaremos a realizar la demostración usando la tabla Persona.Contact( de la base de datos AdventureWorks) que contiene 19972 registros. Para esto se usará el Nested Query anterior y el siguiente SQL Self-Join Query:
SELECT *
FROM PERSON.CONTACT C1,
PERSON.CONTACT C2
WHERE C1.FIRSTNAME = C2.FIRSTNAME
AND C2.MIDDLENAME = 'D'
AND C2.LASTNAME = 'Cox'
Estas dos consultas devuelven el mismo resultado. Claro y desde luego que un Self-Join simplifica mucho el trabajo pero veremos que esto no es conveniente en muchos casos, como tampoco lo es para esta vez. La demostración toma como variables de medida a los planes de ejecución de cada tipo de consulta, donde la consulta:
SELECT *
FROM PERSON.CONTACT C1
WHERE C1.FIRSTNAME IN (SELECT FIRSTNAME
FROM PERSON.CONTACT
WHERE MIDDLENAME = 'D'
AND LASTNAME = 'Cox')
...tiene como plan de ejecución a lo siguiente:

y la para la consulta:
SELECT *
FROM PERSON.CONTACT C1,
PERSON.CONTACT C2
WHERE C1.FIRSTNAME = C2.FIRSTNAME
AND C2.MIDDLENAME = 'D'
AND C2.LASTNAME = 'Cox'
...su plan de ejecución es esto:

Podrás verificar que trabajando con una tabla de 19972 registros (de 15 columnas), un Nested-Join es más óptimo que un Self-Join(me baso en los planes de consulta para afirmar esto). En consecuencia, las diferencias de rendimiento para cada tipo de consulta se verán muy marcadas cuando, por ejemplo, se trabaje sobre varios millones de registros. Es así que se recomienda evaluar el rendimiento de las consultas, ya sea mediante un plan de ejecución u otra forma, para elegir el método a usar para programar sus queries.
Espero que les sea de utilidad todo esto. Todas sus sugerencias y recomendaciones dejénlo por favor como un comment.
Saludos