Você está na página 1de 8

TCNICAS AVANADAS DE SELECT

Autor: Maxwell Borges Fernandes

Este artigo tem o objetivo de demonstrar, atravs de exemplos prticos, tcnicas de SELECT testadas e utilizadas por mim durante toda a minha experincia com bancos de dados relacionais. Os comandos aqui expostos foram testados em Firebird 1.0, porm podem ser aplicados em outros outros servidores devendo-se tomar o cuidado de substituir as sentenas por outras compatveis na nova plataforma. Os pargrafos com o fundo CINZA so as instrues que devem ser digitadas, e os com FUNDO azul so os resultados das consultas. Qualquer ferramenta que aceite a digitao de instrues SQL como o ISQL podem ser utilizados. 1 - Sumarizao em Colunas Imagine que se tenha uma tabela com os campos: Tipo do Animal, Raa, Sexo e Quantidade e que se queira trazer em um nico comando SELECT uma coluna com o tipo do animal, uma com a quantidade de animais fmea e outras com a quantidade de animais macho. Os comandos a seguir tem o objetivo de demonstrar como resolver este problema de forma simples. Providenciando os dados necessrios:
CREATE TABLE (des_tipo nom_raca ind_sexo qtd_animal INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO tab_animal VARCHAR(20), VARCHAR(20), CHAR(1), INTEGER); tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES ('CAO', 'VIRALATA', 'M', 6); ('CAO', 'VIRALATA', 'F', 5); ('CAO', 'PASTOR ALEMAO', 'M', 11); ('CAO', 'PASTOR ALEMAO', 'F', 7); ('CAO', 'DOBERMAN', 'M', 3); ('CAO', 'DOBERMAN', 'F', 9); ('GATO', 'VIRALATA', 'M', 13); ('GATO', 'VIRALATA', 'F', 15); ('GATO', 'SIAMS', 'M', 3); ('GATO', 'SIAMS', 'F', 2); ('GATO', 'ANGOR', 'M', 1); ('GATO', 'ANGOR', 'F', 0);

SELECT * FROM tab_animal; DES_TIPO ===================== CAO CAO CAO CAO CAO CAO GATO GATO GATO GATO GATO GATO NOM_RACA ===================== VIRALATA VIRALATA PASTOR ALEMAO PASTOR ALEMAO DOBERMAN DOBERMAN VIRALATA VIRALATA SIAMS SIAMS ANGOR ANGOR IND_SEXO ======== M F M F M F M F M F M F QTD_ANIMAL ========== 6 5 11 7 3 9 13 15 3 2 1 0

Entendendo o processo: Para resolver este problema iremos utilizar a funo UDF_POS, da biblioteca tbudf que pode ser baixada no site da CFLP. Esta funo retorna a posio de um determinado caracter dentro de uma string. o que precisamos para fazer o nosso SELECT.
SELECT des_tipo, ind_sexo, qtd_animal, UDF_POS('M', ind_sexo) AS macho, UDF_POS('F', ind_sexo) AS femea FROM tab_animal; DES_TIPO ===================== CAO CAO CAO CAO CAO CAO GATO GATO GATO GATO GATO GATO IND_SEXO ======== M F M F M F M F M F M F QTD_ANIMAL ========== 6 5 11 7 3 9 13 15 3 2 1 0 MACHO ===== 1 0 1 0 1 0 1 0 1 0 1 0 FEMEA ===== 0 1 0 1 0 1 0 1 0 1 0 1

Conseguimos com este SELECT fazer com que sempre que aparecer um animal macho a coluna macho venha com 1 e se for fme venha com 0, o mesmo acontecendo com a coluna fmea. Chegando no resultado esperado:
SELECT des_tipo, SUM(qtd_animal * UDF_POS('M', ind_sexo)) AS macho, SUM(qtd_animal * UDF_POS('F', ind_sexo)) AS femea FROM tab_animal GROUP BY des_tipo; DES_TIPO ===================== CAO GATO MACHO ===== 20 17 FEMEA ===== 21 17

2 - Totalizao de Valores/Pesquisa de Saldos Esta tcnica baseada nos conceitos utilizados na tcnica anterior, mas se difere um pouco na forma de aplicao. Em sistemas de Contabilidade e Estoque comum ter-se a necessidade de calcular o saldo de uma conta contbil ou de um item do estoque. A soluo mais comumente utilizada a utilizao de dois SELECT's, um pra buscar a soma das Entradas e outro para buscar a soma das Sadas diminuindose um do outro posteriormente. Esta tcnica ir demonstrar como calcular o saldo de uma conta contbil utilizando-se apenas um SELECT.

Providenciando os Dados:
CREATE TABLE tab_lancamento_contabil (cod_conta INTEGER, val_lancamento DECIMAL(12,2), ind_debito_credito CHAR(1)); INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil tab_lancamento_contabil VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES (1, (1, (1, (1, (1, (2, (2, (2, (2, (2, (2, 100, 'D'); 10, 'C'); 700, 'D'); 30, 'C'); 35.20, 'D'); 72.8, 'C'); 200, 'D'); 1100, 'C'); 120, 'D'); 325, 'C'); 1.30, 'D');

SELECT * FROM tab_lancamento_contabil; COD_CONTA ========= 1 1 1 1 1 2 2 2 2 2 2 VAL_LANCAMENTO ============== 100 10 700 30 35,2 72,8 200 1100 120 325 1,3 IND_DEBITO_CREDITO ================== D C D C D C D C D C D

Achando o Multiplicador:
SELECT cod_conta, val_lancamento, UDF_POS('D', ind_debito_credito) AS val_debito, UDF_POS('C', ind_debito_credito) AS val_credito, UDF_POS('C', ind_debito_credito) * 2 - 1 AS multiplicador FROM tab_lancamento_contabil; COD_CONTA ========= 1 1 1 1 1 2 2 2 2 2 2 VAL_LANCAMENTO ============== 100 10 700 30 35,2 72,8 200 1100 120 325 1,3 VAL_DEBITO ========== 1 0 1 0 1 0 1 0 1 0 1 VAL_CREDITO =========== 0 1 0 1 0 1 0 1 0 1 0 MULTIPLICADOR ============= -1 1 -1 1 -1 1 -1 1 -1 1 -1

Chegando no resultado esperado: Basta agora multiplicar o valor do lanamento pelo multiplicador e agrupar por conta.
SELECT cod_conta, SUM(val_lancamento * (UDF_POS('C', ind_debito_credito) * 2 - 1 )) AS val_saldo FROM tab_lancamento_contabil GROUP BY cod_conta; COD_CONTA ========= 1 2 VAL_SALDO ========= -795,2 1176,5

3 - Descobrindo Quais Sequncias Faltam Algumas vezes necessrio se descobrir quais as sequncias de uma coluna esto faltando. Uma utilizao para esta tcnica descobrir se todas as notas fiscais de um talo de notas foram utilizadas corretamente. Providenciando os Dados:
CREATE TABLE tab_nota_fiscal (num_nota INTEGER); INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO tab_nota_fiscal tab_nota_fiscal tab_nota_fiscal tab_nota_fiscal tab_nota_fiscal tab_nota_fiscal tab_nota_fiscal tab_nota_fiscal VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES (1); (2); (3); (4); (6); (7); (8); (9);

SELECT * FROM tab_nota_fiscal ORDER BY num_nota; NUM_NOTA ======== 1 2 3 4 6 7 8 9

Extraindo os Dados:
SELECT num_nota, (num_nota - (SELECT MAX(num_nota) FROM tab_nota_fiscal WHERE num_nota < b.num_nota) - 1) QTD_FALTA FROM tab_nota_fiscal b ORDER BY 2 DESC; NUM_NOTA ======== 6 2 3 4 7 8 9 1 QTD_FALTA ========= 1 0 0 0 0 0 0 <null>

Analisando o Resultado: O resultado do SELECT nos diz que existe 1 nota anterior nota nmero 6 faltando, ou seja, a nota nmero 5. Se o campo QTD_FALTA tivesse com valor 2 significaria que as notas 5 e 4 estariam faltando.. 4 - Fazendo Anlises Combinatrias Imagine que se tenha duas tabelas, uma de cidades e outras de meios de transporte, e se queira saber todos os meios possveis de se locomover para determinada cidade. Iremos usar para isso o prprio mecanismo de produto cartesiano do Firebird. Providenciando os Dados:
CREATE TABLE tab_cidade (nom_cidade VARCHAR(20)); INSERT INTO tab_cidade VALUES ('SO PAULO'); INSERT INTO tab_cidade VALUES ('RIO DE JANEIRO'); INSERT INTO tab_cidade VALUES ('BRASILIA'); SELECT * FROM tab_cidade; NOM_CIDADE ===================== SO PAULO RIO DE JANEIRO BRASILIA

CREATE TABLE tab_transporte (des_transporte VARCHAR(20)); INSERT INSERT INSERT INSERT INTO INTO INTO INTO tab_transporte tab_transporte tab_transporte tab_transporte VALUES VALUES VALUES VALUES ('TREM DE FERRO'); ('CARRO'); ('AVIAO'); ('NIBUS');

SELECT * FROM tab_transporte; DES_TRANSPORTE ===================== TREM DE FERRO CARRO AVIAO NIBUS

Obtendo o Resultado:
SELECT nom_cidade, des_transporte FROM tab_cidade, tab_transporte ORDER BY nom_cidade; NOM_CIDADE ===================== BRASILIA BRASILIA BRASILIA BRASILIA RIO DE JANEIRO RIO DE JANEIRO RIO DE JANEIRO RIO DE JANEIRO SO PAULO SO PAULO SO PAULO SO PAULO DES_TRANSPORTE ===================== AVIAO CARRO NIBUS TREM DE FERRO AVIAO CARRO NIBUS TREM DE FERRO AVIAO CARRO NIBUS TREM DE FERRO

5 - Consultas Inteligentes Algumas vezes necessrio oferecer uma opo de filtro ao usurio, mas ao mesmo tempo permitir que aquele campo no seja filtrado e que sejam selecionados todos os registros. Uma forma de fazer isso mudar a clusula SQL atravs de programao. Outra alternativa um pouco mais dinmica o uso de Consultas Inteligentes.

Providenciando os dados necessrios:


CREATE TABLE (des_tipo nom_raca ind_sexo qtd_animal INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO tab_animal VARCHAR(20), VARCHAR(20), CHAR(1), INTEGER); tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal tab_animal VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES ('CAO', 'VIRALATA', 'M', 6); ('CAO', 'VIRALATA', 'F', 5); ('CAO', 'PASTOR ALEMAO', 'M', 11); ('CAO', 'PASTOR ALEMAO', 'F', 7); ('CAO', 'DOBERMAN', 'M', 3); ('CAO', 'DOBERMAN', 'F', 9); ('GATO', 'VIRALATA', 'M', 13); ('GATO', 'VIRALATA', 'F', 15); ('GATO', 'SIAMS', 'M', 3); ('GATO', 'SIAMS', 'F', 2); ('GATO', 'ANGOR', 'M', 1); ('GATO', 'ANGOR', 'F', 0);

SELECT * FROM tab_animal; DES_TIPO ===================== CAO CAO CAO CAO CAO CAO GATO GATO GATO GATO GATO GATO NOM_RACA ===================== VIRALATA VIRALATA PASTOR ALEMAO PASTOR ALEMAO DOBERMAN DOBERMAN VIRALATA VIRALATA SIAMS SIAMS ANGOR ANGOR IND_SEXO ======== M F M F M F M F M F M F QTD_ANIMAL ========== 6 5 11 7 3 9 13 15 3 2 1 0

Montando a Consulta Inteligente: SELECT* FROM tab_animal WHERE ((ind_sexo = :PIndSexo) OR (:PIndSexo = 'T')); Montando o Funcionamento da Consulta: Se ao parmetro PIndSexo for atribuido o valor T, toda a clusula WHERE ser VERDADEIRA retornando todos os registros. Caso seja atribudo algum valor diferente de T somente sero retornados os registros em que o campo ind_sexo for igual a esse valor. 6 - Concluso Espero ter conseguido mostrar com este artigo formas de se resolver problemas de extrao de dados vivenciados no dia a dia. Me ative apenas s tcnicas que considero o 'pulo do gato' e que resolveram grandes dores de cabea minha. Apesar de no ter feito comparaes, posso afirmar, por experincia, que a maioria das

tcnicas apresentadas tem uma melhor performance se comparadas tcnicas alternativas. Qualquer dvida ou sugesto pode ser feita atravs do meu email.

Artigo Original Maxwell B Fernandes


(Colaborador da CFLP)

maxwell@rezendesistemas.com.br

Comunidade Firebird de Lngua Portuguesa Visite a Comunidade em: http://www.comunidade-firebird.org

A Comunidade Firebird de Lngua Portuguesa foi autorizada pelo Autor do Original para divulgar este trabalho

Você também pode gostar