Anti join

Las bases de datos relacionales (Oracle, SQL Server, Access, MySQL, etc) están basadas en el álgebra relacional. Dicha álgebra la desarrolló el ingeniero británico Edgar F. Codd en 1970 mientras trabajaba para IBM, pero el gigante azul tardó en desarrollar su primera base de datos relacional por preferir seguir explotando los ingresos de su base de datos IMS/DB. Mientras IBM se dedicaba a rentabilizar al máximo su inversión, otras empresas se llevaron el gato al agua al desarrollar sus propios sistemas relacionales a partir de los papeles de Codd. Habían cambiado para siempre las bases de datos.

Codd proporcionó las bases teóricas para las bases de datos relacionales y para los lenguajes que las manipulan. El rey de estos lenguajes es SQL, Structured Query Language. Ahora bien, lo llamo rey por lo extendido que está desde hace décadas, pues curiosamente tiene una carencia importante muy llamativa: no implementa el antijoin que define los papeles de Codd, sin que aparentemente tenga ninguna dificultad su implementación.

Si definimos el semijjoin (el left o right join de siempre) entre dos tablas A y B como:

Es decir, el left semijoin de las tablas A y B es la unión de todos los elementos a que pertenezcan a A junto con al menos uno de b  que pertenezca/n a B y que satisfagan una función sobre a U b. Esta función hace referencia al campo o campos de ambas tablas que hacemos servir para el join, usando sintaxis de MySQL sería

FROM A LEFT JOIN B ON (A.id = B.id)

El antijoin se definiría así:

Es decir, el antijoin de las tablas A y B es la unión de todos los elementos que satisfacen la función sobre a U b a que pertenezcan a A y no pertenezcan a B.

Desgraciadamente SQL no dispone de algo como:

FROM A ANTI JOIN B ON (A.id = B.id)

Y toca ir haciendo apaños como:

FROM A
WHERE A.id NOT IN(
SELECT id
FROM B)

O la supuesta optimización:

FROM A
LEFT JOIN B ON A.id = B.id
WHERE B.id IS NULL

Que producirá resultados inesperados si el campo pivote es nulo en algún registro de B.

Personalmente no veo que sea técnicamente más complicado implementar en los sistemas gestores de bases de datos un antijoin que otros tipos de join, pero el hecho es que de momento ninguno de los sistemas más extendidos lo incorpora en su dialecto SQL.


Editado el 22/01/2020:

En la última versión de MySQL, la 8.0.17, se va a optimizar el «apaño» antes explicado traduciendo la cláusula IN internamente como ANTIJOIN, según se comenta en la documentación. Podemos encontrar más información aquí.

Un comentario en «Anti join»

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.