Blog Navicat

La SQL Semi Join Oct 15, 2024 by Robert Gravelle

La mayoría de los desarrolladores y administradores de bases de datos están familiarizados con los tipos estándar de JOIN: interna, externa, izquierda y derecha. Si bien estos se pueden escribir utilizando ANSI SQL, existen otros tipos de “joins” que se basan en operadores de álgebra relacional que no tienen una representación de sintaxis en SQL. Hoy veremos uno de estos tipos: “Semi Join”. La semana que viene abordaremos la unión “Anti Join”. Para comprender mejor cómo funcionan estos tipos de uniones, ejecutaremos algunas consultas SELECT en Navicat Premium Lite 17 contra la base de datos PostgreSQL dvdrental database. Esta es una base de datos gratuita que se basa en la base de datos de muestra MySQL Sakila.

Explicación de las Semi Joins

Imagínese por un momento que ANSI SQL admitiera Semi Joins. Si así fuera, la sintaxis probablemente sería similar a la de la extensión de sintaxis de Cloudera Impala, que es LEFT SEMI JOIN y RIGHT SEMI JOIN. Sabiendo esto, así es como podría verse una consulta que utiliza una Semi Join:

SELECT *
FROM actor
LEFT SEMI JOIN film_actor USING (actor_id)

La consulta anterior devolvería todos los actores que actuaron en películas. El problema es que no queremos ninguna película en los resultados ni queremos varias filas del mismo actor. Solo queremos que cada actor aparezca una vez (o cero veces) en el resultado. La palabra "Semi" tiene su origen en el latín y se traduce como "mitad" en inglés. Por lo tanto, nuestra consulta implementa solo "la mitad de la unión", en este caso, la mitad izquierda. En SQL, hay dos sintaxis alternativas que podemos usar para lograr una Semi Join: EXISTS e IN.

Semi Joins con EXISTS

A continuación, se muestra el equivalente de la “Semi Join” con EXISTS:

SELECT *
FROM actor a
WHERE EXISTS (
  SELECT * 
  FROM film_actor fa
  WHERE a.actor_id = fa.actor_id
)

Si ejecutamos nuestra consulta en Navicat Premium Lite 17, podemos ver que funciona tal como se esperaba:

semi_join_exists (147K)

En lugar de utilizar una join, el operador EXISTS comprueba la presencia de una o más filas para cada actor en la tabla film_actor. Gracias a la cláusula WHERE, la mayoría de las bases de datos podrán reconocer que estamos realizando una SEMI JOIN en lugar de una sentencia EXISTS() normal.

Semi Joins con IN

IN y EXISTS son emulaciones de SEMI JOIN exactamente equivalentes, por lo que la siguiente consulta nos traerá exactamente los mismos resultados en la mayoría de las bases de datos con la consulta anterior EXISTS:

SELECT *
FROM actor
WHERE actor_id IN (
  SELECT actor_id FROM film_actor
)

A continuación, se muestra de nuevo la consulta anterior y sus resultados en Navicat Premium Lite 17:

semi_join_in (157K)

EXISTS es considerada la sintaxis más potente (aunque un poco más detallada).

Conclusión

En el blog de hoy hemos aprendido ha emular una Semi Join mediante la sintaxis ANSI SQL. Además de ser la solución óptima en términos de "corrección", también tiene algunos beneficios de rendimiento el usar una “SEMI” Join en lugar de una INNER JOIN, ya que la base de datos deja de buscar coincidencias tan pronto como encuentra la primera.

¿Está interesado en probar Navicat Premium Lite 17? Puede descargarlo para una prueba completa de 14 días. Está disponible para los sistemas operativos Windows, macOS y Linux.

Compartir
Archivos del Blog