Bajemos los Resultados: EXISTS y NOT EXISTS en MySQL

Resulta que necesitaba un listado de ciertos id que no estuvieran en otra tabla, para esto, y estando algo oxidado con MySQL, me puse a tratar de resolverlo con la conjunción y la intersección, pero el costo de procesamiento era demasiado alto.

Haciendo lujo de mis dotes pensativas, busqué por el manual oficial hasta dar con la respuesta que necesitaba, la cual no sólo es sencilla, sino eficiente.

La idea es que EXISTS y NOT EXISTS son condiciones de MySQL que se usan con Subqueries. EXISTS y NOT EXISTS funcionan como IN o NOT IN con subconsultas.

 


¿Qué es EXISTS y NOT EXISTS?


EXISTS verifica si la subconsulta contiene algunas filas y, en caso afirmativo, EXISTS devuelve verdadero. NOT EXISTS satisface si la subconsulta no devuelve filas. EXISTS es más eficiente y optimizado que IN porque devuelve tan pronto como se encuentre el primer valor en la tabla. Por eso IN tiene un rendimiento lento.

Tradicionalmente, MySQL documentó que una subconsulta EXISTS comienza con SELECT *; pero finalmente uno puede restringirlas con el uso de aliases y demás.

Comprendamos un EXISTS y NOT EXISTS con ejemplos:

 

Paso 1:

En primer lugar, creemos dos tablas, una es usuarios y otra es órdenes. Aquí está la declaración para crear ambas.

CREATE TABLE `users` (
 `user_id` int (11) NOT NULL AUTO_INCREMENT,
 `user_name` varchar (255) NOT NULL,
 PRIMARY KEY (`user_id`)
) ENGINE = InnoDB AUTO_INCREMENT = 6 DEFAULT CHARSET = latin1
 
CREATE TABLE `orders` (
 `order_id` int (11) NOT NULL AUTO_INCREMENT,
 `user_id` int (11) NOT NULL,
 PRIMARY KEY (`order_id`)
) ENGINE = InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET = latin1

 

Paso 2:

A continuación, inserte algunos registros en ambas tablas usando las siguientes consultas:

 

INSERT INTO `users` (` user_id`, `user_name`) VALUES (NULL, 'Bhumi'),
                                                    (NULL, 'Zinal'),
                                                    (NULL, 'Ankit'),
                                                    (NULL, 'Jigisha'),
                                                    (NULL, 'Ronil');
 
INSERT INTO `orders` (` order_id`, `user_id`) VALUES (NULL, '2'),
                                                    (NULL, '3');

 

Paso 3:

Ahora, revisemos la consulta EXISTS y NOT EXISTS:

SELECT * FROM `users` WHERE EXISTS (SELECT * from orders WHERE users.user_id = orders.user_id);

 

Esta consulta devolverá todas las filas de los usuarios de la tabla con el id_paquete coincidente de los usuarios de la tabla padre que existe en las órdenes de la tabla de subconsulta. Si el conjunto de resultados de la subconsulta es NULL, el resultado de esta consulta estará vacío. (en castellano, si el usuario tiene pedido aparece en el resultado)

 

SELECT * FROM `users` WHERE NOT EXISTS (SELECT * from orders WHERE users.user_id = orders.user_id);

Esta consulta proporcionará un resultado totalmente inverso de la primera consulta. Devolverá todas las filas de los usuarios que no tengan filas de user_id en la tabla de pedidos. (en castellano, todos los usuarios que no tengan pedidos)

Esto, que es tan sencillo, es muy útil cuando se manejan tiendas de ventas de productos, donde los usuarios tienen descuentos de acuerdo a lo que ya han comprado.

Perdí toda una tarde hasta que lo entendí…

Deja un comentario