?>
1-mysql Básico
Exercícios
?>

Capítulo 2

4-Operações em Conjunto

A SQL oferece suporte as seguintes operações de conjunto.

  • UNION (União)

  • UNION ALL (União Completa)

  • INTERSECT (União)

  • MINUS (diferença)

União - UNION

Quando realizamos junções entre tabelas, formamos uma relação resultante com as colunas que contêm as colunas das tabelas originais.

Porém podem existir situações em que seja necessário recuperar outras linhas (que não as da junções), por exemplo.

Podemos ter ainda situações que requerem resultados de consultas que não são relacionadas mas que o resultado de ambas sejam importantes.

Em situações como essas usamos as Uniões.

O predicado UNION é utilzado posicionado entre dois comandos de consulta:



SELECT col1,col2
from tabela1
UNION [all]
select col3,col4
from tabela2


A operação de conjunto UNION é usada para combinar as saídas de duas ou mais instruções SELECT.

Ele elimina saídas duplicadas.

(se desejarmos que linhas repetidas apareçam, devemos utilizar o predicado ALL logo após o UNION, veja na próxima seção)

Existem somente duas regras para o UNION:

  1. os comandos devem retornar o mesmo número de colunas;

  2. as colunas correspondentes em cada comando devem possuir os mesmos tipos de dados

Exemplo 1

Exemplo 1

                            



mysql> create database conjuntos;
Query OK, 1 row affected (0,10 sec)

mysql> use conjuntos
Database changed
mysql> create table tab1 (id int, valor int);
Query OK, 0 rows affected (0,49 sec)

mysql> create table tab2 (id int, valor int);
Query OK, 0 rows affected (0,40 sec)


mysql> insert into tab1 values (1 ,1),(2,1),(3,2),(4,3),(5,3),(6,4);
Query OK, 6 rows affected (0,05 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> select * from tab1;
+------+-------+
| id   | valor |
+------+-------+
|    1 |     1 |
|    2 |     1 |
|    3 |     2 |
|    4 |     3 |
|    5 |     3 |
|    6 |     4 |
+------+-------+
6 rows in set (0,00 sec)


mysql> insert into tab2 values (1,0),(2,1),(3,2),(4,3),(5,4),(6,5);
Query OK, 6 rows affected (0,08 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> select * from tab2;
+------+-------+
| id   | valor |
+------+-------+
|    1 |     0 |
|    2 |     1 |
|    3 |     2 |
|    4 |     3 |
|    5 |     4 |
|    6 |     5 |
+------+-------+
6 rows in set (0,00 sec)


mysql> select * from tab1
    -> union
    -> select * from tab2;
+------+-------+
| id   | valor |
+------+-------+
|    1 |     1 |
|    2 |     1 |
|    3 |     2 |
|    4 |     3 |
|    5 |     3 |
|    6 |     4 |
|    1 |     0 |
|    5 |     4 |
|    6 |     5 |
+------+-------+

mysql> select * from tab1 union select * from tab2
    -> order by id;
+------+-------+
| id   | valor |
+------+-------+
|    1 |     1 |
|    1 |     0 |
|    2 |     1 |
|    3 |     2 |
|    4 |     3 |
|    5 |     3 |
|    5 |     4 |
|    6 |     4 |
|    6 |     5 |
+------+-------+
9 rows in set (0,00 sec)



                        

Repare que as linhas iguais não aparecem na união

Exemplo2

Vamos usar o banco de dados livraria para esse segundo exemplo com UNION

Liste os títulos dos livros cujo assunto é "Banco de Dados" ou que foram lançados por editoras que contenham "Mirandela" no nome.

Exemplo 2

                            
Select titulo
from livro
    INNER JOIN ASSUNTO
    on ASSUNTO = SIGLA
where descricao = 'banco de dados'

UNION

select titulo
from livro
    INNER JOIN editora E
   on editora = e.codigo
where nome LIKE '%mirandela'


-------------------------------------------------

mysql> select titulo from livro inner join assunto on assunto = sigla 
where descricao = "banco de dados" 
union 
select titulo from livro 
inner join editora E on editora = E.codigo 
where nome LIKE "mirandela%";

+-----------------------------------+
| titulo                            |
+-----------------------------------+
| Banco de Dados para Web           |
| Banco de Dados na Bioinformática  |
| Programando em Linguagem C        |
+-----------------------------------+
3 rows in set (0.00 sec)


                        

UNION ALL

Esta operação é semelhante à Union. Mas também mostra as linhas duplicadas.

Veja o exemplo a seguir, com nosso banco "conjuntos" criado no exemplo 1.

Exemplo 3

                            

mysql> select * from tab1 union ALL select * from tab2 order by id;
+------+-------+
| id   | valor |
+------+-------+
|    1 |     1 |
|    1 |     0 |
|    2 |     1 |
|    2 |     1 |
|    3 |     2 |
|    3 |     2 |
|    4 |     3 |
|    4 |     3 |
|    5 |     3 |
|    5 |     4 |
|    6 |     4 |
|    6 |     5 |
+------+-------+
12 rows in set (0,00 sec)








mysql> select valor from tab1 union  select valor from tab2;
+-------+
| valor |
+-------+
|     1 |
|     2 |
|     3 |
|     4 |
|     0 |
|     5 |
+-------+
6 rows in set (0,00 sec)

mysql> select valor from tab1 union ALL  select valor from tab2;
+-------+
| valor |
+-------+
|     1 |
|     1 |
|     2 |
|     3 |
|     3 |
|     4 |
|     0 |
|     1 |
|     2 |
|     3 |
|     4 |
|     5 |
+-------+
12 rows in set (0,00 sec)




                        

Interseção - INTERSECT(SQL, Intersect)

O operador INTERSECT é um operador de conjunto que retorna apenas linhas distintas de duas ou mais consultas.

O operador INTERSECT compara os conjuntos de resultados de duas consultas e retorna as linhas distintas que são geradas por ambas as consultas.

Para usar o operador INTERSECT para duas consultas, siga estas regras:

  • A ordem e o número de colunas na lista de seleção das consultas devem ser iguais.

  • Os tipos de dados das colunas correspondentes devem ser compatíveis.

O diagrama a seguir ilustra o operador INTERSECT.

intersecao

Apesar de existir na estrutura da linguagem SQL, no mysql não existe a cláusula intersect. Para obter uma interseção, temos que usar os recursos já vistos. Acompanhe o exemplo a seguir.


Exemplo 4: Intersect no mysql

                            


CREATE TABLE t1 ( id INT PRIMARY KEY ); CREATE TABLE t2 LIKE t1; INSERT INTO t1(id) VALUES(1),(2),(3); INSERT INTO t2(id) VALUES(2),(3),(4); mysql> show tables; +----------------------+ | Tables_in_intersect1 | +----------------------+ | t1 | | t2 | +----------------------+ 2 rows in set (0.00 sec) mysql> select * from t1; +----+ | id | +----+ | 1 | | 2 | | 3 | +----+ 3 rows in set (0.00 sec) mysql> select * from t2; +----+ | id | +----+ | 2 | | 3 | | 4 | +----+ 3 rows in set (0.00 sec)

Criando o INTERSECT no mysql a partir de INNER JOIN

Exemplo 4, continuação

                            

mysql> SELECT DISTINCT id  FROM t1 INNER JOIN t2 USING(id);
+----+
| id |
+----+
|  2 |
|  3 |
+----+
2 rows in set (0.00 sec)


                        

Essa forma de gerar a interseção se dá assim:

  • A cláusula INNER JOIN retorna linhas das tabelas da esquerda e da direita.

  • O operador DISTINCT remove as linhas duplicadas.

Lembrando que USING substiu o ON para o JOIN.

USING é útil quando ambas as tabelas compartilham uma coluna com o mesmo nome exato na junção.

Como USING executa uma junção de igualdade e só pode ser usado quando os nomes das colunas são idênticos, não é necessário incluir a coluna duas vezes. Disso resulta que quando usamos USING, não precisamos prefixar o nome da coluna com o nome da tabela!

Criando o INTERSECT Usando IN e subquery

Podemos criar a interseção usando uma subconsulta. Veja a continuação do exemplo 4 a seguir:

Exemplo 4, continuação

                            

mysql> SELECT DISTINCT id FROM t1 WHERE id IN (SELECT id FROM t2);
+----+
| id |
+----+
|  2 |
|  3 |
+----+
2 rows in set (0.00 sec)



                        

Essa forma de criar o intersect funciona assim:

  1. A subconsulta retorna o primeiro conjunto de resultados.

  2. A consulta externa usa o operador IN para selecionar apenas os valores que existem no primeiro conjunto de resultados.

  3. O operador DISTINCT garante que apenas valores distintos sejam selecionados.

Exemplo 5

No exemplo a seguir criamos o INTERSECT no banco "conjuntos", na coluna valor.

Exemplo 5

                            


mysql> select distinct valor from tab1
    -> inner join tab2
    -> using(valor);
+-------+
| valor |
+-------+
|     1 |
|     2 |
|     3 |
|     4 |
+-------+
4 rows in set (0,00 sec)


                        

Exemplo de INTERSECT no Banco de Dados livraria

Liste os títulos dos livros cujo assunto é "Programação" e que foram lançados por uma editora que contenha a palavra "Mirandela" no nome, sem repetições.

NA SQL:

    

    Select titulo
from livro
    INNER JOIN ASSUNTO
    on assunto = sigla
where descricao = "programação"
INTERSECT
select titulo
from livro
    INNER JOIN editora E
    on editora = e.codigo
where nome like "%mirandela"
    

No mysql

Exemplo 6

                            

select distinct titulo from livro
inner join assunto on assunto = sigla 
where descricao = 'programação' 
and titulo in 
(
 select titulo from livro
  inner join editora E on editora = E.codigo
   where nome like '%mirandela%'
);
+----------------------------+
| titulo                     |
+----------------------------+
| Programando em Linguagem C |
+----------------------------+
1 row in set (0.00 sec)



                            
                        

Diferença (EXCEPT/MINUS/NOT IN)

As cláusulas EXCEPT e MINUS da SQL são duas maneiras de se obter a diferença entre dois conjuntos (ambas fazem a mesma coisa).

A diferença é que EXCEPT está disponível no banco de dados PostgreSQL, enquanto MINUS está disponível em Oracle e SQL Server.

No mysql usamos NOT IN junto com uma subquery.

A figura abaixo ilustra o resultado de uma operação de diferença entre em conjuntos.

diferenca

Na linguagem SQL podemos usar:

    
    SELECT id FROM t1
MINUS
SELECT id FROM t2; 
ou 
SELECT id FROM t1
EXCEPT
SELECT id FROM t2; 
    

Mas no mysql temos que usar NOT IN, como mostrado a seguir.

Exemplo: Encontre os valores que estão na tabela 1 e NÃO ESTÃO na tabela 2:

Exemplo 7

                            
mysql> select id from t1 where id not in (select id from t2);
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0,00 sec)

mysql> select id from t2 where id not in (select id from t1);
+----+
| id |
+----+
|  4 |
+----+
1 row in set (0,00 sec)



                            
                        

Exemplo 8: Banco "conjuntos"

Veja que a operação DIFERENÇA de conjuntos depende de quem está do lado direito ou do lado esquerdo.

Ou seja, dados dois conjuntos C1 e C2, fazer C1-C2 é diferente de fazer C2-C1.

Nesse exemplo fazemos as operações de diferença entre as duas tabelas do banco conjuntos.

Exemplo 8

                            


mysql> select t1.valor as 'valor-tab1',t2.valor as 'valor-tab2' from tab1 t1 join tab2 t2 
    -> on t1.id = t2.id;
+------------+------------+
| valor-tab1 | valor-tab2 |
+------------+------------+
|          1 |          0 |
|          1 |          1 |
|          2 |          2 |
|          3 |          3 |
|          3 |          4 |
|          4 |          5 |
+------------+------------+
6 rows in set (0,00 sec)

mysql> select valor as v1 from tab1 t1
    -> where valor not in
    -> (select valor from tab2 t2);
Empty set (0,00 sec)

mysql> select valor as v2 from tab2 t2 where valor not in (select valor from tab1 t1);
+------+
| v2   |
+------+
|    0 |
|    5 |
+------+
2 rows in set (0,00 sec)





                            
                        

No exemplo acima, mostramos primeiramente os valores das colunas "valor" das tabelas tab1 e tab2. Depois fazermos as diferenças entre tab1 e tab2 (tab1-tab2) e entre tab2 e tab1 (tab2-tab1).

Repare que não há elemento em tab1 que não esteja em t2 (resultado da consulta foi "empty"). Mas na diferença t2-t1 encontramos como resultado os elementos 0 e 5.

voltar ao início da página