Usando CASE no Oracle SQL.

Fala PessoAll,

Bom, conforme prometido no Post anterior, estou aqui para dar uma apimentada na utilização da função DECODE usando SQL Oracle.

A funcionalidade que iremos falar hoje é a CASE. Esta funcionalidade é muito boa e dá uma dinâmica muito interessante a comandos SQL, em muitas vezes nos poupando de ter que fazer uma Stored Prodecure ou uma Function para fazer alguma coisa que um simples SQL pode resolver.

Para não fugir dos costumes… vamos ao exemplo.

Suponha que você tenha 3 classificações diferentes para seus vendedores, que funcionam da seguinte forma: Se o cara vendeu entre R$0.00 e R$1,000.00 ele é classificado como “Ruim”, se foi entre R$1,001.00 e R$4,000.00 ele é classificado como “Bom”, se foi entre R$4,001.00 e R$8,000.00 ele é classificado como “Ótimo” e se for acima de R$8,001.00 ele é considerado como “Fenomenal”, e você precisa exibir isso no relatório para sua gerência.

Como fazer isso?

Aí você começa a pensar…
DECODE? Não dá… tenho faixa de valores, e não valores específicos!

Cria uma View? Não… uma view é um mero Select, não vai resolver!

Ah…. claro! Cria uma função!!! Na função eu passo o valor que o cara vendeu e ela me retorna qual a classificação do cara! Perfeito!
É…. funcionar vai funcionar, mas você tem que criar um objeto no banco, tem que criar um Script, tem que se preocupar com Grant’s e todos os demais aspectos para que criemos um novo objeto!

Não seria mais simples que no próprio Select a gente resolvesse esse problema? SIM!!! Claro!! Porque não. Para isso, vamos usar a funcionalidade CASE. Como faríamos isso, para este caso?

Agora sim, cenário montado, vamos ao exemplo (de verdade):


select v.nome_vendedor,
ve.mes,
ve.vlr_meta,
ve.vlr_venda,
case
when ve.vlr_venda between 0 and 1000 then
'Ruim'
when ve.vlr_venda between 1001 and 4000 then
'Bom'
when ve.vlr_venda between 4001 and 8000 then
'Ótimo'
when ve.vlr_venda >= 8001 then
'Fenomenal'
end classificacao_vendedor
from vendedores v,
vendas ve
where ve.cod_vendedor = v.cod_vendedor;
and ve.mes = '07/2009';

Que beleza não? Resolvido nosso provlema! Temos agora em nosso SQL a coluna classificacao_vendedor que nos dá a informação que precisamos, sem problemas com criação de função nem nada do tipo!

Bom não? Simples de usar, rápido e tudo quanto é de vantagem!

É isso aí, creio que a partir desse exemplo dá pra “voar” bem alto! Agora é só adaptar para sua necessidade e tá tudo certo!!

Espero que gostem e comentem!

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

25 ideias sobre “Usando CASE no Oracle SQL.

  1. Paolo

    Bom dia,
    Muita bom o seu post, utilizo CASE em vários casos, porém, tenho uma dúvida:
    Teria como eu retornar o valor do campo caso nenhuma das condições do CASE fosse satisfeita?
    Por exemplo:
    CASE WHEN nome_coluna = ‘A’ THEN ‘Ativo’

    Neste caso, eu gostaria que se o valor da coluna não fosse ‘A’, exibisse o valor mesmo; teria como?

    Responder
        1. oracle Autor do post

          Obrigado pelo seu comentário lander.
          Desta forma funciona, mas não atenderia a necessidade do comentário do nosso outro colega, que tinha A, e outros tipos que não apenas I de Inativo. Desta forma que você mencionou realmente seria melhor se os únicos valores possíveis fosse Ativo e tudo que fosse diferente disso fosse Inativo, que não era o caso.

          Para estes casos, onde podemos ter outros valores fora da faixa que conhecemos utilizamos o ELSE, que faz parte do CASE para resolver.

          Obrigado e volte sempre ao blog.

          Abraços!

          Responder
  2. Fabio Carvalho

    Pessoal, existe uma forma de usar a função Case para Join de Tables diferentes tipo o exemplo abaixo.

    Case when
    join tbrfat311700 g on c.t$refi = g.t$refg
    join tbrfat002700 l on g.t$refi = l.t$refi and g.t$lino = l.t$lino
    join tbrawm200700 w on g.t$refi = w.t$refir and g.t$lino = w.t$linor
    when
    join tbrfat002700 l on c.t$refi = l.t$refi
    join tbrawm200700 w on c.t$refi = w.t$refir and l.t$lino = w.t$linor END

    Ou voces saberiam me informar como deveria ser para que retornasse algo para uma das duas situações.

    Desde Já Agradeço…

    Responder
    1. oracle Autor do post

      Bom dia Fabio.

      Obrigado pela postagem no site http://www.diaadiaoracle.com.br, desculpe a demora em responder, estava de férias.

      Bom, o CASE não serve para esta demanda que você tem de alterar os joins.
      Mas… explica melhor o que você precisa fazer que tento te ajudar.

      Grande abraço!

      Responder
      1. Karen Monteiro

        Bom dia!

        Preciso de algo muito pareciso. Por favor me dá uma forcinha.

        Exemplo: Tenho uma tabela que tem datas de 1 a 31/dez.
        E outra com Id_mês (‘yyyy-mm-01′)

        Quero cruzar assim: Se a data da tabela “A” for de 1 a 18 cruza com o campo id_mes da tabela “B” onde for ‘2014-11-01′

        Se for de 19 a 31/dez cruza com o campo id_mes da tabela “B” onde for ‘2014-12-01′

        Se não, terei informações duplicadas, pois ele trará por exemplo as informações de um dia expecífico, 2 vezes, 1 referente ao id_mês 11 e outra do id_mes 12

        Dá pra fazer isso?

        Não estou acertando a Sintax.

        Responder
  3. Robson Ribeiro Faxas

    Só uma observação… Nesse exemplo, o valor “8001” não entra em nenhum dos condicionais, percebeu? hehe

    O mais parabéns! Bem claro!

    Responder
    1. oracle Autor do post

      Perfeito Robson.

      Exemplo corrigido.
      Neste caso, espero que nenhum vendedor tenha vendo R$8001 exatos, cado contrário ia ficar sem classificação, nos casos onde não se encaixa em nenhuma condição, retorna null.

      Obrigado.

      Abraços!

      Responder
  4. Filipe

    Olá! Há como fazer uso do case para definir se eu listo um registro ou não?
    Por exemplo:
    case when quantidade 0 then “lista registro”
    else
    “não lista registro”

    Responder
    1. oracle Autor do post

      Olá Filipe.
      Obrigado pela visita e por seu comentário ao site.

      Não consegui entender exatamente sua necessidade, mas “não listado” vou entender como sendo uma restrição para não retornar o registro.
      Então… neste caso, seria um filtro na cláusula “where” da sua query e não com case, que ficaria assim:


      select *
      from tabela
      where quantidade > 0;

      Logo…. só seriam listados todos os registros que a quantidade seja um valor maior que zero. Os demais serão ignorados e não retornados na consulta.

      É isso mesmo que você precisa?
      Se entendi errado, só avisar que tentamos esclarecer.

      Grande abraço!!

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

      Responder
  5. ilton

    Veja se consegue me ajudar:
    Tenho uma tabela funcionarios e as colunas:
    classe (int)
    admissao (data)
    demissao (data)

    preciso saber em um intervalo de data por exemplo: 01/01/2014 a 31/01/2014, quantos
    funcionarios foram admitidos e quantos foram demitidos, preciso que minha consulta saia assim:
    classe admissao demissao
    1 10 0
    2 2 8
    3 0 14
    assim por diante
    isso esta agrupado por classe
    agradeço desde já

    Ilton

    Responder
    1. oracle Autor do post

      Boa tarde.

      Antes de mais nada, obrigado pela visita ao site.
      Acredito que consigo te ajudar sim.

      Uma forma de fazer seria algo assim:

      select int, sum(qtdadm), sum(qtddem)
      from (
      select int, count(1) qtdadm, 0 qtddem
      from funcionarios
      where admissao between to_date('01/01/2014', 'DD/MM/YYYY')
      and to_date('01/02/2014', 'DD/MM/YYYY')
      group by int
      union all
      select int, 0 qtdadm, count(1) qtddem
      from funcionarios
      where demissao between to_date('01/01/2014', 'DD/MM/YYYY')
      and to_date('01/02/2014', 'DD/MM/YYYY')
      group by int
      ) group by int

      Veja abaixo uma massa que montei aqui, e como ficou:

      create table tduvida(int number, dtadmissao date, dtdemissao date);

      insert into tduvida values (1, to_date('01/01/2014', 'dd/mm/yyyy'), to_date('01/06/2014', 'dd/mm/yyyy'));
      insert into tduvida values (1, to_date('01/02/2014', 'dd/mm/yyyy'), to_date('01/07/2014', 'dd/mm/yyyy'));
      insert into tduvida values (1, to_date('01/03/2014', 'dd/mm/yyyy'), to_date('01/08/2014', 'dd/mm/yyyy'));

      insert into tduvida values (2, to_date('01/01/2014', 'dd/mm/yyyy'), to_date('01/06/2014', 'dd/mm/yyyy'));
      insert into tduvida values (2, to_date('01/02/2014', 'dd/mm/yyyy'), to_date('01/07/2014', 'dd/mm/yyyy'));
      insert into tduvida values (2, to_date('01/03/2014', 'dd/mm/yyyy'), to_date('01/08/2014', 'dd/mm/yyyy'));

      insert into tduvida values (3, to_date('01/01/2014', 'dd/mm/yyyy'), to_date('01/06/2014', 'dd/mm/yyyy'));
      insert into tduvida values (3, to_date('01/02/2014', 'dd/mm/yyyy'), to_date('01/07/2014', 'dd/mm/yyyy'));
      insert into tduvida values (3, to_date('01/03/2014', 'dd/mm/yyyy'), to_date('01/08/2014', 'dd/mm/yyyy'));

      commit;

      select * from tduvida

      select int, sum(qtdadm), sum(qtddem)
      from (
      select int, count(1) qtdadm, 0 qtddem
      from tduvida
      where dtadmissao between to_date('01/01/2014', 'DD/MM/YYYY')
      and to_date('01/02/2014', 'DD/MM/YYYY')
      group by int
      union all
      select int, 0 qtdadm, count(1) qtddem
      from tduvida
      where dtdemissao between to_date('01/01/2014', 'DD/MM/YYYY')
      and to_date('01/02/2014', 'DD/MM/YYYY')
      group by int
      ) group by int

      Abraços!

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

      Responder

Deixe uma resposta

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