Gerencie suas informações através de instruções SQL com selects turbinados (para leigos e experts)

Para programadores e DBAs pode não ser muita novidade, mas certamente é uma reflexão de que a gestão da informação não seria a mesma sem ele. E para o usuário menos experiente a mensagem é de que SQL não é coisa de outro mundo e pode fazer parte e facilitar sua vida.

[ Hits: 21.792 ]

Por: Perfil removido em 09/04/2010


"Isso é simples, é só fazer um select"



Por muitas vezes eu já ouvi essa frase, e, entre os colegas de profissão, quem já não ouviu: "Isso é simples, é só fazer um select"!? Virou até motivo de brincadeira. Mas isso não deixa de ser verdade...

Como eu já comentei, algumas coisas aqui não são novidade para os profissionais da área, e ao mesmo tempo não são algo inatingível para os não-profissionais. Mas, independente de qualquer contrariedade eu gostaria de citar por serem recursos que são realmente uma mão na roda - não necessariamente é uma abordagem muito avançada, é praticamente apenas algo bem parcial dentro deste universo, mas são coisas que eu pessoalmente acho bem interessantes e úteis.

Subselect - Um select dentro de outro, ou seja, dando um select em um select

É claro que SQL é muito mais do que select, mas como a proposta exposta no título é falar principalmente dele vamos limitar o nosso foco. Outra razão é que boa parte das lógicas do select podem ser estendidas às outras instruções.

Também vale ressaltar que existem quase que inúmeras funções que podem ser agregadas e combinadas nas instruções de select, e que, existe um padrão, mas elas podem variar de um banco de dados pro outro, mudando alguns detalhes na sintaxe, ordem ou até mesmo tipo e número de recursos, mas nada que seja uma Torre de Babel, são particularidades muito sutis (meus exemplos foram feitos no Firebird).

Indo ao nosso primeiro exemplo na prática, podemos agrupar vários selects na mesma tabela numa única instrução trazendo na nossa listagem um resultado processado que dispensa intervenções de programação no aplicativo cliente, já que o servidor de banco de dados pode nos entregar os resultados dentro de uma organização final desejada. O exemplo é simplório e consequentemente um pouco forçado mas isso é proposital para uma ilustração objetiva.

Digamos que tenhamos uma tabela onde registramos títulos a serem recebidos. Esta tabela tem apenas o código, a descrição e o valor de cada título. Numa outra tabela temos os lançamentos que registram os recebimentos destes títulos, logo, para sabermos se um título foi totalmente pago precisamos verificar a somatória destes lançamentos e comparar com o valor dele na primeira tabela.
Linux: Gerencie suas informações através de instruções SQL com selects turbinados (para leigos e experts)
Acontece que nossa tabela de lançamentos é bem simples e só registra o código do lançamento, o número do documento referente, o valor e o tipo do lançamento.

Se quisermos saber o total pendente de um título precisamos somar e agrupar os valores dos lançamentos, obter o saldo e subtraí-lo do valor da nossa primeira tabela onde está o registro do cadastro do título, são basicamente dois passos distintos.

E se nesta seleção quisermos listar apenas aqueles cujo total pendente seja maior que 0 (zero) temos mais um passo a ser considerado no processo que é a aplicação do filtro.

Podemos fazer isso separadamente e processar na aplicação cliente combinando os três resultados ou então o servidor pode entregar tudo processado pra gente num único SQL.

select
   DOCUMENTO,
   DESCRICAO,
   VALORTOTAL,
   TOTALPENDENTE
from (
   select
      DOCUMENTO,
      DESCRICAO,
      VALOR as VALORTOTAL,
      (VALOR - sum(VALORPAGO - VALORESTORNADO)) as TOTALPENDENTE
   from (
      select D.DOCUMENTO,
         D.DESCRICAO,
         D.VALOR,
         sum(iif(L.TIPO = 'RECEBIMENTO', L.VALORLANCAMENTO, 0)) as VALORPAGO,
         sum(iif(L.TIPO = 'ESTORNO', L.VALORLANCAMENTO, 0)) as VALORESTORNADO
      from LANCAMENTOS as L
         right join DOCUMENTOS as D on (D.DOCUMENTO = L.DOCUMENTO)
         group by
            D.DOCUMENTO,
            D.DESCRICAO,
            D.VALOR
   )
   group by
      DOCUMENTO,
      DESCRICAO,
      VALOR
   )
where TOTALPENDENTE = 0

Descrevendo nosso SQL de dentro pra fora (como vemos temos três SQLs, um dando select no outro), no primeiro fazemos uma seleção somando o valor do lançamento dividido em duas expressões com if nas quais se o tipo for RECEBIMENTO temos um campo virtual com o valor pago (positivo) e se for ESTORNO temos o valor estornado (negativo), isso agrupado por documento (e descrição e valor pra atender a um requisito de organização no processamento do banco), além de que buscamos aí os dados da tabela do cadastro do título junto e usamos right join para retornarmos um registro com saldo de lançamentos igual a zero caso não haja lançamentos pro título.

Depois temos um outro SQL que dá select no primeiro select e obtém o saldo entre o que foi pago e estornado e subtrai esse saldo do valor do título pra obter o total pendente.

Por fim temos nosso SQL mais superficial que dá select nesse select intermediário e filtra por total pendente maior que 0 (zero), tendo o resultado que era esperado no parágrafo anterior.
Linux: Gerencie suas informações através de instruções SQL com selects turbinados (para leigos e experts)
É claro que esse é exemplo e até exagerado tendo em vista as nossas tabelas simples do exemplo, eles podiam até ser mais compactos, mas o objetivo foi exemplificar que algo do tipo é possível quando você tiver um situação mas escabrosa pela frente.

Caberia aqui também de certa forma o recurso de views (não vou abordar aqui, mas vale a pena você dar uma pesquisada), só que no caso de relatórios ou consultas simples e rápidas, principalmente se seu usuário não tiver privilégios no banco pra criar views, nosso exemplo acaba sendo mais viável.

Subselect - Passando um select como parâmetro pra um campo na cláusula where de outro select

Vejamos como exemplo a divisão dos grupos da Copa do Mundo. Cada grupo tem quatro países [e eu agora não me lembro quantos grupos são e nem quais os países de cada grupo, mas não vem ao caso, é só um exemplo]. Bem, eu quero saber então quais os países que o Brasil vai enfrentar na fase classificatória (por pontos dentro do grupo), mas eu nem sei de que grupo o Brasil é, muito menos os países do grupo dele.
Linux: Gerencie suas informações através de instruções SQL com selects turbinados (para leigos e experts)
É outro exemplo bem forçado, mas pela lógica devo primeiro saber de que grupo o Brasil é e depois achar os outros países de seu grupo. Analisando tecnicamente, temos a lista dos países com o nome deles, seu código e o código do grupo a que pertencem - tendo este último código eu seleciono novamente os países que tem esse mesmo código e pronto. Num único SQL fica assim:

select
  G.NOME,
  P.PAIS
from
  GRUPOS G
join
  PAISES P
on
  (P.CODGRUPO = G.CODGRUPO)
where
  G.CODGRUPO = (
     select
       CODGRUPO
     from
       PAISES
     where
        PAIS = 'BRASIL'
   )

Eu acho o código do grupo do BRASIL na tabela de países no select entre parênteses que automaticamente é passado como parâmetro pro select principal que relaciona as tabelas de grupos e países (note que usei só join pois o Firebird, assim como outros bancos, aceita isso como comando abreviado para 'inner join'). E assim temos o resultado que esperávamos, descobrindo o nome do grupo e os países que fazem parte dele.
Linux: Gerencie suas informações através de instruções SQL com selects turbinados (para leigos e experts)
Num resumo conceitual, isso serve pra encontrarmos todos os itens de um grupo a partir de um único item deste grupo sem conhecermos os outros itens do grupo ou sequer conhecer a identificação de vínculo do grupo (código do grupo, por exemplo).

Página anterior     Próxima página

Páginas do artigo
   1. Do dBASE ao Firebird
   2. "Isso é simples, é só fazer um select"
   3. Só mais uma e vamos concluir
Outros artigos deste autor

Como escolher o melhor escalonador de CPU para melhorar o desempenho da máquina

Criando um álbum de fotos no Linux

Block Hosts: Bloqueando ataques de força-bruta (brute force) em FTP, SSH e outros

Pós-instalação do Sabayon LXDE

expr - Definição e uso do comando

Leitura recomendada

Implementação LDAP e Java

OpenAI - Como usar uma Inteligência Artificial a seu favor

Injeção de SQL

Instalando o poderoso banco de dados IBM DB2!

MongoDB Aggregation

  
Comentários
[1] Comentário enviado por dastyler em 14/04/2010 - 11:30h

Apesar da minha humilde pessoa já conhecer SQL e estar até meio "enjoado " de trabalhar com a mesma (apesar que me ajuda muuuuitissimo até hoje), o artigo ficou muito bom.
Serve até como um guia de referencia para quando esquecer alguma regra...heheheheh!

abraço!



[2] Comentário enviado por grandmaster em 03/05/2010 - 17:14h

Exato dastyler, server como um guia.

Ficou realmente muito didático, pelo menos para mim que já tenho alguma noção.

--
Renato de Castro Henriques
ITILv3 Foundation Certified
CobiT Foundation 4.1 Certified ID: 90391725
http://www.renato.henriques.nom.br


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts