Union x Union ALL — Select’s no Oracle

Fala PessoAll,

Vamos com mais uma dica interessante sobre Oracle.
Vamos analisar desta vez, os comandos UNION e UNION ALL. Estes comandos servem para que possamos unir mais de uma query (select) em um mesmo comando, trazendo os resultados de ambas as query’s. Que? Entendeu nada!? Vamos lá:

Existe no Oracle a possibilidade de unirmos mais de um comando select de forma que possamos obter o resultados de todos eles unidos (claro!) em um único resultado, como se fosse um comando só, como assim?

Suponha que você possui uma tabela de clientes e uma tabela de funcionários, e você quer trazer todos os códigos e nomes de clientes e funcionários para exibir em um relatório? Como fazer isso? Assim:


Select codcli,
nom_cli,
'C' tipo
from clientes
union
Select cod_func,
nom_func,
'F'
from funcionarios;

Se vocês executarem este comando, teremos todos os clientes e todos os funcionários listados em um mesmo resultado, mas… temos algumas coisas a considerar.

1 – Vocês devem ter notado que os nomes das colunas das tabelas são diferentes, quando eu rodar que nome minha coluna vai ter? O nome das colunas da primeira query da lista de comandos, a primeira query vai mandar em tudo e as colunas do resultado vão receber o nome das colunas da primeira query.

2 – Quando usamos o comando UNION, temos obrigatóriamente que ter a mesma quantidade de colunas e o mesmo tipo de dados das colunas em todas as query’s. Como assim? Suponha que na tabela clientes a coluna cod_cli tenha tipo de dados number e na tabela funcionarios a coluna cod_func tenha tipo de dados varchar2, não pode! Ao executar este comando o banco vai retornar um erro dizendo que as colunas das query’s não estão corretamente relacionadas. Como em ambos os comandos elas são a primeira coluna da query e estarão relacionadas, ambas tem que ter o mesmo tipo.

3 – Não podemos utilizar ORDER BY nas query’s envolvidas, apenas na última query, que ordernará os registros de todas as query’s. Neste caso acima, por exemplo, se na ultima query colocássemos um ORDER BY 1 por exemplo, ele ordenaria o resultado das duas query’s juntas, como se fosse um comando só. Se tiver códigos iguais nas duas query’s, serão trazidos juntos, pois os resultados serão considerados juntos na hora de ordenar.

Outra coisa que comentei no início foi o UNION ALL, qual a diferença dele pro UNION? O UNION utilizado sozinho faz um distinct no resultado da query, ou seja, se tiverem resultados repitidos eles não serão exibidos, será exibida apenas uma ocorrência. Suponha que por coincidência tenhamos um cliente com código 1 e nome CICERO e tenhamos um funcionario com código 1 e nome CICERO também, caso não tivéssemos essa coluna tipo para diferenciar os registros de clientes e funcionários teríamos a ocorrência 1 CICERO apenas uma vez em nosso resultado. Já usando o UNION ALL, independente da quantidade de registros repetidos que sejam retornados, todos serão exibidos.

Como usa? Assim:


Select codcli,
nom_cli,
'C' tipo
from clientes
union all
Select cod_func,
nom_func,
'F'
from funcionarios;

Qual a diferença? Só o all depois do union, depois disso o resto o Oracle resolve. Espero esse tal de Oracle!!

Momento DBA: Para o banco, por não precisar se preocupar em verificar se existem resultados iguais para que exiba apenas um deles, o UNION ALL tem bem menos custo para ser executado, portanto, se você tiver query’s em que você tem certeza que não serão retornados valores repetidos (como essa do exemplo, em que temos uma coluna tipo para diferenciar) use sempre UNION ALL, seu DBA e seu Banco de Dados agradecem!

É isso pessoal, espero que tenham entendido e que gostem.
Qualquer dúvida, sugestão, reclamação etc não deixem de entrar em contato.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

8 ideias sobre “Union x Union ALL — Select’s no Oracle

  1. Gustavo Romão Gonzales

    Olá amigo, gostaria de um esclarecimento. Para fazer um script de remoção de dados duplicados. O que seria mais rápido ? Fazer a remoção na aplicação ou fazer com a ENGINE do banco com uma tabela temporária ?

    Responder
    1. oracle Autor do post

      Bom dia Gustavo.

      Acredito que as duas opções são válidas, porém, fazendo na aplicação você teá que fazer a exclusão manualmente. Já com um bloco PL/SQL de banco você pode automatizar esta atividade.
      Não sei de quantas linhas estamos falando neste processo, mas… algumas dicas.

      1 – Criar uma nova tabela, com uma PK com as colunas que são chave e não podem duplicar, em seguida ler a tabela atual e ir inserindo na tabela nova, com um tratamento de erro: “DUP_VAL_ON_INDEX”, que ocorre quando a chave tenta ser violada, e aí neste caso não precisaria de tratamento.
      2 – Fazer uma cópia da tabela usando “create as select” e depois fazer o inverso com um “insert select distinct”.
      3 – Renomear a tabela atual, criar uma nova com o nome correto e depois fazer o “insert select distinct”.

      Tem inúmeras soluções, só precisa ver qual a melhor pra você.

      Abraços e muito obrigado pela visita.

      Atc.
      Gerson Júnior
      gerson.vasconcelos@gmail.com

      Responder
    1. oracle Autor do post

      Olá Romeu!
      Acredito que esta função que você está querendo utilizar seja do MySQL. No Oracle ela não existe.
      Pelo que entendi (não pesquisei a fundo), ela conta a quantidade de linhas retornadas de um determinado comando.

      No Oracle, é possível fazer a mesma coisa com a função “count”.
      Usa assim:

      select count(1) from tabela; –> Retorna quantidade de linhas da tabela, já que não tem filtros.
      select codcliente, count(1) from tabela_pedidos group by codcliente; –> Retorna a quantidade de pedidos de um determinado cliente.

      Como pode ver, ela é uma função de grupo, logo, para utilização é necessário agrupamento dos dados retornados.

      Maiores informações você pode obter na documentação da Oracle.
      http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions032.htm

      Espero que te ajude.

      Abraços.

      Atc.
      Gerson Júnior
      gerson.vasconcelos@gmail.com

      Responder

Deixe uma resposta para Marcelo Cancelar resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *