8th Jul 2024 10 minutos de leitura O operador SQL EXISTS Ignacio L. Bisso aprender sql noções básicas de sql Índice Sintaxe do operador EXISTS Exemplo de banco de dados: Barcos e carros de luxo Exemplos do operador SQL EXISTS Exemplo 1: Localizando produtos vendidos Exemplo 2: usando o operador NOT EXISTS Exemplo 3: Usando EXISTS com NOT EXISTS Praticando o operador EXISTS Exercício 1: Pedidos antigos Exercício 2: Compradores de motores de barcos Exercício 3: Never Bought Continue expandindo suas habilidades com o operador EXISTS do SQL O uso da cláusula SQL EXISTS nos permite criar consultas complexas de forma simples. Conheça os prós e os contras do operador EXISTS neste artigo. No SQL, o operador EXISTS nos ajuda a criar condições lógicas em nossas consultas. Essencialmente, ele verifica se há alguma linha em uma subconsulta. Mostraremos a você a sintaxe do EXISTS, forneceremos alguns exemplos de uso e faremos vários exercícios para você praticar. Se estiver começando a usar SQL ou precisar de uma atualização em SQL, recomendo o curso SQL para Iniciantes. Ele inclui tópicos de SQL que vão desde SELECTs básicos até tópicos complexos como junções, agregações e subconsultas. É uma ótima maneira de desenvolver, atualizar ou expandir suas habilidades em SQL. Sintaxe do operador EXISTS Você provavelmente conhece os operadores SQL como =, >, < e LIKE. Todos esses operadores podem ser usados para criar condições lógicas que retornarão TRUE ou FALSE. Exemplos de condições comuns incluem: WHERE Employee_id = 10345 WHERE Price < 1000 WHERE Name LIKE ‘John%’ Os operadores =, < e LIKE comparam dois elementos ou operandos. Essa é a razão pela qual são chamados de operadores binários. WHERE EXISTS ( subquery ) Agora vamos ver a consulta SQL inteira para determinar onde a condição EXISTS pode ser colocada: SELECT columns FROM table1 WHERE EXISTS (SELECT columns FROM table2); O operador EXISTS é usado para criar condições booleanas para verificar se uma subconsulta retorna linha(s) ou um conjunto vazio. Quando a subconsulta retorna pelo menos uma linha, EXISTS retorna TRUE. Não importa quantas linhas são retornadas ou quantas colunas estão na lista da subconsulta SELECT. Somente quando a subconsulta retorna 0 linhas é que EXISTS retorna FALSE. É importante observar que nenhuma das linhas retornadas pela subconsulta é mostrada no resultado final. Exemplo de banco de dados: Barcos e carros de luxo Vamos examinar vários exemplos de consultas com base em um banco de dados de amostra de uma empresa que vende carros e barcos de luxo. A empresa mantém o controle dos carros e barcos na tabela product, que tem as colunas 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 O banco de dados também tem uma tabela Client tabela com as colunas client_id, client_name e country. client_idclient_namecountry 10John F.United States 11Samid A,Kuwait 12Majal H.Brunei 13Pierre B.France 14Abdul E.Kuwait Por fim, há a tabela sale com as colunas product_id, client_id, sale_date. (Para simplificar, omito a ideia de ter uma tabela para pedidos de compra; nesse tipo de empresa, um cliente normalmente compra apenas um produto por 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 Exemplos do operador SQL EXISTS Exemplo 1: Localizando produtos vendidos Para o primeiro exemplo de consulta, suponha que o gerente de marketing queira saber quais carros e barcos foram vendidos entre 1º e 15 de abril de 2024. A consulta abaixo faz isso: 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 Há outras maneiras de escrever essa consulta sem usar o operador EXISTS. Entretanto, para explicar como o operador EXISTS funciona, esse é um bom exemplo de nível básico. A consulta principal SELECT é muito fácil; ela vai para a tabela product para obter a coluna product_name. Entretanto, não queremos todos os product_names na tabela. Queremos apenas os produtos que retornam TRUE para a seguinte condição: 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’ ) Se analisarmos a condição, a subconsulta retornará todos os registros de vendas de um determinado produto (p1.product_id) e de um período específico (2024-04-01 a 2024-04-15). Se a subconsulta retornar registros, então EXISTS retornará TRUE. Se a subconsulta não retornar nenhum registro, EXISTS retornará FALSE. Observe que a subconsulta é executada várias vezes - uma vez para cada linha lida pela consulta externa. Esses tipos de subconsultas que são executadas uma vez para cada linha processada na consulta principal são chamadas de "subconsultas correlacionadas" e têm suas particularidades. Se você quiser se aprofundar nesse tópico, sugiro o artigo Correlated Subquery in SQL: Um guia para iniciantes. Exemplo 2: usando o operador NOT EXISTS Agora, suponha que o gerente queira os nomes dos veículos que não foram vendidos no mesmo período. Esse tipo de consulta - em que buscamos registros que não existem no banco de dados - é excelente para o operador NOT EXISTS. Afinal de contas, estamos pesquisando elementos que não existem no banco de dados. A consulta é a seguinte: 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 Depois de entendermos como o operador EXISTS funciona no SQL, entender NOT EXISTS é muito simples; é o oposto. Se EXISTS retornar TRUE, então NOT EXISTS retornará FALSE e vice-versa. Neste exemplo, a consulta principal tem uma cláusula WHERE com duas condições. A primeira condição é solicitar produtos do tipo "veículo". A segunda condição usa NOT EXISTS para manter apenas os produtos que não tiveram vendas durante o período de 2024-04-01 a 2024-04-15. Em outras palavras, procuramos produtos para os quais a subconsulta retorna um conjunto de resultados vazio, ou seja, para os quais não há vendas nesse período. Em alguns casos, podemos resolver esse tipo de consulta usando NOT IN com uma subconsulta. Nessa consulta específica, podemos colocar essa 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’ ) Entretanto, há uma diferença na forma como a consulta é executada internamente no banco de dados. A condição da subconsulta NOT IN é executada uma vez, enquanto a condição da subconsulta NOT EXISTS é executada uma vez por cada linha. É isso mesmo; NOT EXISTS é uma subconsulta correlacionada. Leia os artigos 5 exemplos de subconsultas SQL e Operador SQL IN para saber mais sobre esses operadores. Exemplo 3: Usando EXISTS com NOT EXISTS Em seguida, precisamos de uma lista dos clientes que não compraram um barco durante o verão de 2023, mas compraram um barco durante o inverno anterior (ou seja, de dezembro de 2022 a março de 2023). A consulta para obter esse relatório é: 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 ) ; Results (Resultados): client_idClient_nameCountry 11Samid A.Kuwait Após os dois exemplos anteriores, este exemplo não deve ser muito difícil de entender; é a combinação de ambos. A ideia é selecionar o registro inteiro (SELECT *) da tabela client e, em seguida, usar um EXISTS para verificar se um barco foi comprado no inverno passado. Depois disso, usamos NOT EXISTS para verificar se um barco não foi comprado no verão passado. Observe que ambas as subconsultas têm um JOIN entre o sale e product porque precisamos usar as colunas product_type e sale_date nas condições WHERE. Neste ponto, gostaria de esclarecer algo sobre subconsultas correlacionadas. Já mencionamos que as subconsultas correlacionadas são executadas uma vez por cada candidato a linha. Esse fato pode afetar o desempenho de toda a consulta, especialmente quando trabalhamos com tabelas grandes. Em resumo, o operador EXISTS (e as subconsultas correlacionadas) é um recurso SQL poderoso para determinados tipos de consultas. No entanto, devemos evitar subconsultas correlacionadas se estivermos trabalhando com tabelas grandes. Praticando o operador EXISTS Como em muitas outras linguagens de computador, aprender SQL fazendo exercícios é uma das melhores maneiras de adquirir habilidades. Portanto, nesta seção, mostrarei três exercícios do operador EXISTS de diferentes complexidades. Exercício 1: Pedidos antigos Exercício: O proprietário da empresa quer saber quais produtos (carros ou barcos) não foram pedidos nos últimos 365 dias. Solução: 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 Explicação: A consulta principal usa a tabela product para obter a coluna product_name. A cláusula WHERE dessa consulta é a parte principal. Ela tem uma condição NOT EXISTS que é avaliada como TRUE para os produtos que não foram vendidos no último ano. A condição s.sale_date >= CURRENT_DATE - 365 na subconsulta obtém todas as linhas do último ano. Observe que a subconsulta retorna uma constante ( 1 ). Isso ocorre porque o fato importante sobre a subconsulta é quantas linhas ela retorna, não o conteúdo das linhas retornadas; portanto, podemos colocar uma coluna ou uma constante como 1. Exercício 2: Compradores de motores de barcos Exercício: Nossa empresa é famosa por fabricar um motor para barcos e temos alguns clientes que só compram esse produto. O departamento de marketing quer identificar os clientes que só compram motores para barcos, para que possa segmentar esses clientes em uma campanha de marketing. Solução: 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 Explicação: Este exercício tem uma cláusula WHERE com duas condições. A primeira condição usa um operador EXISTS para verificar se o cliente selecionado pela consulta externa comprou um motor de barco. A segunda condição WHERE usa NOT EXISTS para verificar se o mesmo cliente (o cliente selecionado pela consulta externa) nunca comprou nenhum outro tipo de produto. Se você quiser explorar mais exercícios de subconsulta, recomendo o artigo SQL Subquery Practice: 15 Exercises with Solutions (Prática de subconsulta SQL: 15 exercícios com soluções). Exercício 3: Never Bought Exercício: O proprietário da empresa deseja um relatório Never Bought . O relatório deve ter apenas duas colunas: client_name e product_name. O conteúdo do relatório deve ser o complemento da tabela sale tabela. Em outras palavras, se um cliente nunca comprou um produto, então o par formado por este client_name e este product_name deve estar no relatório. Solução: Há duas abordagens para resolver este exercício: Usando NOT EXISTS. Usando o operador de conjunto EXCEPT (ou MINUS). Mostraremos as duas abordagens. Solução usando 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 parciais da 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 Explicação: O primeiro ponto a ser entendido é o resultado dessa parte da consulta: SELECT c1.client_name, p1.product_name FROM client c1, product p1 Como não estamos unindo corretamente as tabelas client e producto resultado é um produto cartesiano - um conjunto de todos os pares <client_name, product_name> possíveis. Quando tivermos todos os pares possíveis, continuaremos a descartar esses pares na tabela sale usando o operador NOT EXISTS. Solução usando 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 Explicação: A primeira parte dessa abordagem é semelhante à solução anterior; criamos todos os pares cliente-produto possíveis. Em seguida, usando o operador EXCEPT, removemos os pares que estão na tabela sale tabela. Isso obtém os pares que estamos procurando. Aqui está a diferença: Na segunda parte do EXCEPT, precisamos JOIN a tabela sale tabela com os operadores product e client tabelas. Continue expandindo suas habilidades com o operador EXISTS do SQL Neste artigo, abordamos os operadores EXISTS e NOT EXISTS com vários exemplos. Também explicamos os prós e os contras das subconsultas correlacionadas. Para os leitores que desejam aumentar suas habilidades em SQL, recomendo o curso Trilha de Práticas em SQL track. Você encontrará centenas de exercícios sobre tópicos de SQL, como JOINs, GROUP BY, HAVING, subconsultas e até mesmo o operador EXISTS. Se estiver apenas começando a usar SQL ou precisar de uma atualização, recomendo nosso SQL para Iniciantes curso. Ao aumentar suas habilidades em SQL, você investe em você! Tags: aprender sql noções básicas de sql