8th Jul 2024 Lectura de 11 minutos El Operador SQL EXISTS Ignacio L. Bisso aprender SQL princípios básicos de SQL Índice Sintaxis del operador EXISTS Ejemplo de base de datos: Barcos y coches de lujo Ejemplos del operador EXISTS de SQL Ejemplo 1: Búsqueda de productos vendidos Ejemplo 2: Uso del Operador NOT EXISTS Ejemplo 3: Usando EXISTS con NOT EXISTS Practicando el Operador EXISTS Ejercicio 1: Órdenes Antiguas Ejercicio 2: Compradores de motores de barcos Ejercicio 3: Nunca Comprado Continúe Expandiendo sus Habilidades con el Operador SQL EXISTS El uso de la cláusula SQL EXISTS nos permite crear consultas complejas de forma sencilla. Conozca los pros y los contras del operador EXISTS en este artículo. En SQL, el operador EXISTS nos ayuda a crear condiciones lógicas en nuestras consultas. Esencialmente, comprueba si hay alguna fila en una subconsulta. Te mostraremos la sintaxis de EXISTS, te daremos algunos ejemplos de uso y te propondremos varios ejercicios para que practiques. Si estás empezando con SQL o necesitas un repaso de SQL, te recomiendo el curso SQL para principiantes. Incluye temas de SQL que van desde los SELECT básicos hasta temas complejos como uniones, agregaciones y subconsultas. Es una buena forma de desarrollar, refrescar o ampliar tus conocimientos de SQL. Sintaxis del operador EXISTS Probablemente esté familiarizado con operadores SQL como =, >, < y LIKE. Todos estos operadores se pueden utilizar para crear condiciones lógicas que devolverán TRUE o FALSE. Algunos ejemplos de condiciones comunes son: WHERE Employee_id = 10345 WHERE Price < 1000 WHERE Name LIKE ‘John%’ Los operadores =, <, y LIKE comparan dos elementos u operandos. Esta es la razón por la que se llaman operadores binarios. WHERE EXISTS ( subquery ) Ahora veamos la consulta SQL completa para determinar dónde se puede colocar la condición EXISTS: SELECT columns FROM table1 WHERE EXISTS (SELECT columns FROM table2); El operador EXISTS se utiliza para crear condiciones booleanas para verificar si una subconsulta devuelve fila(s) o un conjunto vacío. Cuando su subconsulta devuelve al menos una fila, EXISTS devuelve TRUE. No importa cuántas filas se devuelvan ni cuántas columnas haya en la lista de la subconsulta SELECT. Sólo cuando la subconsulta devuelve 0 filas, EXISTS devuelve FALSE. Es importante señalar que ninguna de las filas devueltas por la subconsulta se muestra en el resultado final. Ejemplo de base de datos: Barcos y coches de lujo Examinemos varias consultas de ejemplo basadas en una base de datos de ejemplo de una empresa que vende coches y barcos de lujo. La empresa lleva un registro de los coches y barcos en la tabla product, que tiene las columnas product_id, product_name, product_price, product_type. product_idproduct_nameproduct_priceproduct_type 100Ferrari F203000000Car 101Lamborghini AX3600000Car 102Pagani Zonda4300000Car 200VanDutch 582100000Boat 201Lamborghini B93400000Boat 202VanDutch 561800000Boat 300Boat Engine Yamei 1001000000Boat La base de datos también tiene una tabla Client con las columnas client_id, client_name y country. client_idclient_namecountry 10John F.United States 11Samid A,Kuwait 12Majal H.Brunei 13Pierre B.France 14Abdul E.Kuwait Por último, existe la tabla sale tabla con las columnas product_id, client_id, sale_date. (Para simplificar, omito la idea de tener una tabla para las órdenes de compra; en este tipo de empresa, un cliente normalmente compra sólo un producto a la vez). client_idproduct_idcountry 102002020-03-05 101012024-04-05 112022023-03-05 121022021-03-07 121002023-03-05 122022024-04-09 133002022-03-05 103002020-07-19 133002023-11-25 Ejemplos del operador EXISTS de SQL Ejemplo 1: Búsqueda de productos vendidos Para el primer ejemplo de consulta, supongamos que el director de marketing quiere saber qué coches y barcos se vendieron entre el 1 y el 15 de abril de 2024. La siguiente consulta lo hace: SELECT product_name FROM product p1 WHERE EXISTS ( SELECT * FROM sale s WHERE s.product_id = p1.product_id AND s.sale_date >= ‘2024-04-01’ AND s.sale_date <= ‘2024-04-15’ ) Resultados: Product_name Lamborghini AX VanDutch 56 Hay otras formas de escribir esta consulta sin utilizar el operador EXISTS. Sin embargo, para explicar cómo funciona el operador EXISTS, éste es un buen ejemplo básico. El SELECT principal es muy sencillo; va a la tabla product para obtener la columna product_name. Sin embargo, no queremos todos los product_names de la tabla. Queremos sólo aquellos productos que devuelvan TRUE para la siguiente condición: WHERE EXISTS ( SELECT * FROM sale s WHERE s.product_id = p1.product_id AND s.sale_date >= ‘2024-04-01’ AND s.sale_date <= ‘2024-04-15’ ) Si analizamos la condición, la subconsulta devuelve todos los registros de ventas de un producto determinado (p1.product_id) y para un periodo de tiempo concreto (2024-04-01 a 2024-04-15). Si la subconsulta devuelve registros, entonces EXISTS devolverá TRUE. Si la subconsulta no devuelve ningún registro, EXISTS devolverá FALSE. Tenga en cuenta que la subconsulta se ejecuta varias veces, una por cada fila leída por la consulta externa. Este tipo de subconsultas que se ejecutan una vez por cada fila procesada en la consulta principal se denominan "subconsultas correlacionadas" y tienen sus particularidades. Si quieres profundizar en este tema, te sugiero el artículo Correlated Subquery in SQL: Guía para principiantes. Ejemplo 2: Uso del Operador NOT EXISTS Supongamos ahora que el gestor quiere los nombres de los vehículos que no se vendieron durante el mismo periodo. Este tipo de consulta -en la que buscamos registros que no existen en la base de datos- es excelente para el operador NOT EXISTS. Al fin y al cabo, estamos buscando elementos que no existen en la base de datos. La consulta es la siguiente SELECT * FROM product p1 WHERE p1.product_type = ‘Car’ AND NOT EXISTS ( SELECT * FROM sale s WHERE s.product_id = p1.product_id AND s.sale_date >= ‘2024-04-01’ AND s.sale_date <= ‘2024-04-15’ ) Resultados: Product_idProduct_nameProduct_priceProduct_type 100Ferrari F203000000Car 102Pagani Zonda4300000Car Una vez que entendemos cómo funciona el operador EXISTS en SQL, entender NOT EXISTS es muy sencillo; es lo contrario. Si EXISTS devuelve TRUE, entonces NOT EXISTS devuelve FALSE y viceversa. En este ejemplo, la consulta principal tiene una cláusula WHERE con dos condiciones. La primera condición es pedir productos del tipo "vehículo". La segunda condición utiliza NOT EXISTS para mantener sólo los productos que no tuvieron ventas durante el periodo 2024-04-01 a 2024-04-15. En otras palabras, buscamos los productos para los que la subconsulta devuelve un conjunto de resultados vacío, es decir, para los que no hay ventas en ese periodo. En algunos casos, podemos resolver este tipo de consulta utilizando NOT IN con una subconsulta. En esta consulta en particular, podemos poner esta cláusula WHERE: WHERE p1.product_type = ‘Car’ AND p1.product_id NOT IN (SELECT s.product_id FROM sale s WHERE s.sale_date >= ‘2024-04-01’ AND s.sale_date <= ‘2024-04-15’ ) Sin embargo, hay una diferencia en la forma en que la consulta se ejecuta internamente en la base de datos. La condición de la subconsulta NOT IN se ejecuta una vez, mientras que la condición de la subconsulta NOT EXISTS se ejecuta una vez por cada fila. Así es; NOT EXISTS es una subconsulta correlacionada. Lea los artículos 5 Ejemplos de Subconsultas SQL y Operador SQL IN para más información sobre estos operadores. Ejemplo 3: Usando EXISTS con NOT EXISTS A continuación, necesitamos una lista de aquellos clientes que no compraron un barco durante el verano de 2023 pero sí lo hicieron durante el invierno anterior (es decir, de diciembre de 2022 a marzo de 2023). La consulta para obtener ese informe es SELECT * FROM client c1 WHERE EXISTS ( SELECT * FROM sale s1 JOIN product p1 ON p1.product_id = s1.product_id WHERE c1.client_id = s1.client_id AND p1.product_type = 'Boat' AND s1.sale_date >= '2022-12-21' AND s1.sale_date <= '2023-03-20' -- winter ) AND NOT EXISTS ( SELECT * FROM sale s2 JOIN product p1 ON p1.product_id = s2.product_id WHERE c1.client_id = s2.client_id AND p1.product_type = 'Boat' AND s2.sale_date >= '2023-6-21' AND s2.sale_date <= '2023-09-20' -- summer ) ; Resultados: client_idClient_nameCountry 11Samid A.Kuwait Después de los dos ejemplos anteriores, este ejemplo no debería ser demasiado difícil de entender; es la combinación de ambos. La idea es seleccionar todo el registro (SELECT *) de la tabla client y después utilizar EXISTS para comprobar que se ha comprado un barco el invierno pasado. Después, utilizamos NOT EXISTS para comprobar que no se ha comprado un barco en el verano pasado. Nótese que ambas subconsultas tienen un JOIN entre los caracteres sale y product porque necesitamos utilizar las columnas product_type y sale_date en las condiciones WHERE. En este punto, me gustaría aclarar algo sobre las subconsultas correlacionadas. Hemos mencionado que las subconsultas correlacionadas se ejecutan una vez por cada fila candidata. Este hecho puede afectar al rendimiento de toda la consulta, especialmente cuando trabajamos con tablas de gran tamaño. En resumen, el operador EXISTS (y las subconsultas correlacionadas) es un potente recurso SQL para ciertos tipos de consultas. Sin embargo, debemos evitar las subconsultas correlacionadas si trabajamos con tablas grandes. Practicando el Operador EXISTS Como muchos otros lenguajes de computación, aprender SQL haciendo ejercicios es una de las mejores formas de adquirir habilidades. Así que en esta sección, mostraré tres ejercicios del operador EXISTS de diferentes complejidades. Ejercicio 1: Órdenes Antiguas Ejercicio: El dueño de la empresa quiere saber qué productos (coches o barcos) no se han pedido en los últimos 365 días. Solución: SELECT p1.product_name FROM product p1 WHERE NOT EXISTS ( SELECT 1 FROM sale s WHERE s.product_id = p1.product_id AND s.sale_date >= CURRENT_DATE - 365 ); Resultados: Product_name Ferrari F20 Pagani Zonda Lamborghini B9 VanDutch 58 Explicación: La consulta principal utiliza la tabla product para obtener la columna product_name. La cláusula WHERE de esta consulta es la parte clave. Tiene una condición NOT EXISTS que evalúa a TRUE para aquellos productos que no se han vendido en el último año. La condición s.sale_date >= CURRENT_DATE - 365 en la subconsulta obtiene todas las filas del último año. Observe que la subconsulta devuelve una constante ( 1 ). Esto se debe a que el dato importante de la subconsulta es cuántas filas devuelve, no el contenido de las filas devueltas; por tanto, podemos poner una columna o una constante como 1. Ejercicio 2: Compradores de motores de barcos Ejercicio: Nuestra empresa es famosa por fabricar un motor para barcos y tenemos algunos clientes que sólo compran este producto. El departamento de marketing quiere identificar a los clientes que sólo compran motores para barcos para poder dirigirse a ellos en una campaña de marketing. Solución: SELECT * FROM client c1 WHERE EXISTS ( SELECT * FROM sale s1 -- they buy boat engines JOIN product p1 ON p1.product_id = s1.product_id WHERE c1.client_id = s1.client_id AND p1.product_name = 'Boat engine' ) AND NOT EXISTS ( SELECT * FROM sale s2 -- they never buy other product JOIN product p2 ON p2.product_id = s2.product_id WHERE c1.client_id = s2.client_id AND p2.product_name <> 'Boat engine' ); Resultados: client_idClient_nameCountry 13Pierre B.France 14Abdul E.Kuwait Explicación: Este ejercicio tiene una cláusula WHERE con dos condiciones. La primera condición utiliza un operador EXISTS para verificar que el cliente seleccionado por la consulta externa ha comprado un motor de barco. La segunda condición WHERE utiliza NOT EXISTS para verificar que el mismo cliente (el cliente seleccionado por la consulta externa) nunca ha comprado otro tipo de producto. Si quieres explorar más ejercicios de subconsultas, te recomiendo el artículo SQL Subquery Practice: 15 Exercises with Solutions. Ejercicio 3: Nunca Comprado Ejercicio: El dueño de la compañía quiere un reporte de Nunca Comprado . El informe debe tener sólo dos columnas: client_name y product_name. El contenido del informe debe ser el complemento de la tabla sale tabla. En otras palabras, si un cliente nunca compró un producto, entonces el par formado por este client_name y este product_name debe estar en el informe. Solución: Hay dos enfoques para resolver este ejercicio: Utilizando NOT EXISTS. Utilizando el operador de conjunto EXCEPT (o MINUS). Mostraremos ambos enfoques. Solución utilizando NOT EXISTS: SELECT c1.client_name, p1.product_name FROM client c1, product p1 WHERE NOT EXISTS ( SELECT 1 FROM sale s WHERE c1.client_id = s.client_id AND p1.product_id = s.product_id ) Resultados parciales de la consulta: Client_nameProduct_name John F.Ferrari F20 John F.Pagani Zonda John F.Lamborghini B9 John F.VanDutch 56 Samid A.Lamborghini AX Samid A.Pagani Zonda Samid A.VanDutch 56 Samid A.Lamborghini B9 Samid A.Boat Engine Yamei 100 Samid A.Ferrari F20 Explicación: El primer punto a entender es el resultado de esta parte de la consulta: SELECT c1.client_name, p1.product_name FROM client c1, product p1 Como no estamos uniendo correctamente las tablas client y productel resultado es un producto cartesiano, es decir, un conjunto de todos los pares posibles de <client_name, product_name>. Una vez que tenemos todos los pares posibles, procedemos a descartar esos pares en la tabla sale mediante el operador NOT EXISTS. Solución utilizando EXCEPT: SELECT c1.client_name, p1.product_name FROM client c1, product p1 EXCEPT SELECT client_name, product_name FROM sale s JOIN product p ON p.product_id = s.product_id JOIN client c ON c.client_id = s.client_id Explicación: La primera parte de este enfoque es similar a la solución anterior; creamos todos los pares posibles cliente-producto. A continuación, mediante el operador EXCEPT, eliminamos los pares que se encuentran en la sale tabla. Así obtenemos los pares que buscamos. He aquí la diferencia: En la segunda parte de EXCEPT, necesitamos JOIN la tabla sale con los operadores product y client tablas. Continúe Expandiendo sus Habilidades con el Operador SQL EXISTS En este artículo, cubrimos los operadores EXISTS y NOT EXISTS con varios ejemplos. También explicamos los pros y contras de las subconsultas correlacionadas. A los lectores que deseen ampliar sus conocimientos de SQL, les recomiendo la Ejercicio de SQL pista. Encontrarán cientos de ejercicios sobre temas de SQL como JOINs, GROUP BY, HAVING, subconsultas e incluso el operador EXISTS. Si acaba de iniciarse en SQL o necesita un repaso, le recomiendo nuestro SQL para principiantes curso. Cuando aumentas tus conocimientos de SQL, ¡inviertes en ti! Tags: aprender SQL princípios básicos de SQL