A sintaxe SQL é bem simples e flexível. Mas, as poucas regras devem ser seguidas a risca para que a sua consulta seja devidamente interpretada. Ela se utiliza de palavras chave (keywords) que junto com os outros elementos da linguagem formam as sentenças ou cláusulas (clauses) SQL. Um grupo de sentenças forma um comando (statement).
O comando SELECT é usado para obter dados de uma ou
mais tabelas. Quando um SELECT obtém dados de mais de uma tabela
diz-se que é uma 'junção' (join). O SQL Local suporta a
seguinte sintaxe :
OBS: Para muitas pessoas, uma descrição geral de sintaxe como a
mostrada abaixo pode confundir mais do que ajudar na compreensão
do assunto. Se for este o seu caso, não se preocupe, o assunto
será tratado por partes no decorrer deste trabalho e você
terá, ao final, uma compreensão geral e completa.
SELECT [DISTINCT] column_list
FROM table_reference
[WHERE search_condition]
[ORDER BY order_list]
[GROUP BY group_list]
[HAVING having_condition]
[UNION select_expr]
As clausulas entre colchetes são opcionais.
'column_list' é a lista das colunas (separadas por vírgula) das
quais se obtém os dados.
'table_reference' é uma referência a tabela (ou tabelas) de
onde se obtém os dados.
'search_condition' é uma expressão condicional limitativa.
'order_list' é a lista de colunas para a classificação.
'group_list' é a lista de colunas para o agrupamento.
'having_condition' é uma expressão condicional limitativa.
'select_expr' é um comando Select.
Para começar nosso estudo, vamos utilizar uma tabela
(de nome Funcionarios) destinada a manter registro dos
funcionários de uma empresa, com a seguinte descrição :
OBS: A tabela Funcionarios.db (montada em Paradox 7) está anexa
a este trabalho. Ela contém apenas 7 registros (linhas) e 4
campos (colunas), para agilizar nosso trabalho. E antes que
alguém reclame de baixos salários vale dizer que os dados são
inteiramente aleatórios e não guardam nenhuma correspondência
com a realidade.
MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- -------------- 1 Fernando Bom Gerente 1.500,00 2 Adriano Segundo digitador 780,00 3 Mauricio Bello Digitador 700,00 4 Sebastião Bola Faxineiro 400,00 5 Firmino Pinto Digitador 800,00 6 Carla Lerda Secretária 500,00 7 Madalena Bolha Digitadora 750,00
Sintaxe básica do comando SELECT :
SELECT <NOMES das COLUNAS SEPARADAS
POR VÍRGULA>
FROM <NOME da TABELA>
WHERE <CLAUSULA CONDICIONAL>
ORDER BY <CLAUSULA DE CLASSIFICAÇÃO>
OBS: A sintaxe mostrada é simplificada e tem finalidades
didáticas. A sintaxe completa suporta várias possibilidades
adicionais, algumas das quais, a medida que se tornarem
necessárias, serão apresentadas ao aluno.
Um comando mínimo terá pelo menos duas cláusulas :
Exemplo 1:
SELECT NOME, FUNCAO, MATRICULA
FROM FUNCIONARIOS
Resultado : NOME FUNCAO MATRICULA -------------------- -------------------- --------- Fernando Bom Gerente 1 Adriano Segundo digitador 2 Mauricio Bello Digitador 3 Sebastião Bola Faxineiro 4 Firmino Pinto Digitador 5 Carla Lerda Secretária 6 Madalena Bolha Digitadora 7 Comentários : 1)Note que as colunas são mostradas na ordem em que nós solicitamos (colocamos a MATRICULA, que era a primeira coluna, na última posição). 2)São mostradas somente as colunas que nós solicitamos, a coluna Salário não aparece porque não foi solicitada. 3.Você pode testar os exemplos apresentados aquí usando um dos vários softwares de SQL. Veja na Introdução como utilizar o SQL Explorer do Delphi.
Exemplo 2:
SELECT *
FROM FUNCIONARIOS
Resultado : MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- -------------- 1 Fernando Bom Gerente 5.500,00 2 Adriano Segundo digitador 780,00 3 Mauricio Bello Digitador 700,00 4 Sebastião Bola Faxineiro 400,00 5 Firmino Pinto Digitador 800,00 6 Carla Lerda Secretária 500,00 7 Madalena Bolha Digitadora 750,00 Comentários : 1)O '*' é uma forma abreviada de indicar a seleção de todas as colunas da tabela. A ordem das colunas obedece a ordem natural da tabela. Se quizermos mudar a ordem das colunas não poderemos usar o '*'.
Normalmente, queremos obter de uma tabela apenas certos registros (linhas) que satisfaçam a determinadas condições. A cláusula WHERE tem justamente esta finalidade.
Exemplo 3:
SELECT *
FROM FUNCIONARIOS
WHERE FUNCAO = "Digitador"
Resultado : MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- -------------- 3 Mauricio Bello Digitador 700,00 5 Firmino Pinto Digitador 800,00 Comentários : 1)Há dois funcionários com a função Digitador, ambos foram mostrados. 2)E a Madalena Bolha ? (ela não é Digitador, ela é Digitadora, por isso não foi mostrada); 3)E o Adriano Segundo ?(ele não é Digitador, ele é digitador, por isso não foi mostrado);
Exemplo 4:
SELECT *
FROM FUNCIONARIOS
WHERE FUNCAO = "digitador"
Resultado : MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- --------------
Comentário : Não há nenhum funcionario com função digitador(em minúsculas).
Exemplo 5:
select * from funcionarios where funcao =
"Digitador"
Resultado : MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- -------------- 3 Mauricio Bello Digitador 700,00 5 Firmino Pinto Digitador 800,00 Comentários : 1) O SQL é insensível a caixa, pode estar em minúsculas ou maiúsculas que o resultado é o mesmo... 2) Quanto aos dados a coisa é diferente : Digitador e digitador não são considerados iguais. 3) Você pode colocar as diferentes cláusulas em linhas diferentes, ou lançar na mesma linha.
Antes que sejamos chamados de machistas, vamos tentar incluir também a Madalena Bolha em nossa listagem :
Exemplo 6:
select *
from funcionarios
where funcao like "Digitador%"
Resultado : MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- -------------- 3 Mauricio Bello Digitador 700,00 5 Firmino Pinto Digitador 800,00 7 Madalena Bolha Digitadora 750,00 Comentários : 1) O SQL seleciona todos os funcionários cuja função comece com Digitador. 2) O '%' indica que quaisquer caracteres adicionais devem ser aceitos. Se houvesse Digitadorzinho, Digitadoreiro e etc...eles seriam selecionados.
É, mas e o Adriano Segundo ? Só porque algum digitador digitou "digitador" ao invés de digitar "Digitador" ele vai ficar de fora da lista de Digitadores ?
Exemplo 6:
select *
from funcionarios
where UPPER(funcao) like UPPER("Digitador%")
Resultado : MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- -------------- 2 Adriano Segundo digitador 780,00 3 Mauricio Bello Digitador 700,00 5 Firmino Pinto Digitador 800,00 7 Madalena Bolha Digitadora 750,00 Comentários : 1) UPPER() é uma das funções SQL. Ela transforma todos os caracteres em maiúsculas. 2) Podíamos usar LOWER() que é a função correspondente para minúsculas...
Exemplo 7:
select *
from funcionarios
where UPPER(funcao) like UPPER("Digitador%")
order by nome
Resultado : MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- -------------- 2 Adriano Segundo digitador 780,00 5 Firmino Pinto Digitador 800,00 7 Madalena Bolha Digitadora 750,00 3 Mauricio Bello Digitador 700,00 Comentários : 1) A cláusula ORDER BY nos permite ordenar nossa query. No caso pelo NOME do funcionario. 2) Antes, quando não usávamos ORDER BY, a ordem era a ordem natural da tabela.
Exemplo 8:
select *
from funcionarios
where UPPER(funcao) like UPPER("Digitador%")
order by salario desc
Resultado : MATRICULA NOME FUNCAO SALARIO --------- -------------------- -------------------- -------------- 5 Firmino Pinto Digitador 800,00 2 Adriano Segundo digitador 780,00 7 Madalena Bolha Digitadora 750,00 3 Mauricio Bello Digitador 700,00 Comentários : 1) A palavra chave DESC permite uma classificação em ordem descendente. 2) ASC é o equivalente para ordem ascendente. Por ser default não precisa ser indicada.
As expressões podem conter praticamente qualquer tipo
de variáveis, strings, numéricas ou booleanas.
Os operadores podem ser de vários tipos : aritméticos,
lógicos, de comparação, etc...
Como de praxe, vamos direto a parte prática.
Operadores : Aritméticos : + * / De Comparação : < > = <> >= =< IS NULL IS NOTNULL Lógicos : AND OR NOT Concatenação de Strings : ||
Continuando com o exemplo da nossa tabela Funcionários, suponhamos que a empresa pretenda promover um reajuste geral de 10% nos salários de seus funcionários.
Exemplo 9: SELECT MATRICULA,NOME,SALARIO AS SALARIO_ATUAL, SALARIO*1.10 funcionarios."SALARIO REAJUSTADO" FROM FUNCIONARIOS
Resultado : MATRICULA NOME SALARIO_ATUAL SALARIO REAJUSTADO --------- -------------------- ------------- ------------------ 1 Fernando Bom 5.500,00 6.050,00 2 Adriano Segundo 780,00 858,00 3 Mauricio Bello 700,00 770,00 4 Sebastião Bola 400,00 440,00 5 Firmino Pinto 800,00 880,00 6 Carla Lerda 500,00 550,00 7 Madalena Bolha 750,00 825,00
Comentários :
1)Utilizamos um campo virtual (ou campo calculado) 'SALARIO
REAJUSTADO' para mostrar o valor do novo salário de cada
funcionário, salário este calculado com a expressão
SALARIO*1,15.Note que não se criou nenhum campo novo,
persistente, na tabela, apenas se montou em memória um campo
calculado. Também não se reajustou o salário de ninguém,
apenas exibiu-se quais seriam os valores dos salários
reajustados.
2)Utilizamos, pela primeira vez, aliases (apelidos ou nomes
substitutos) para nomes de campos. O campo SALARIO foi mostrado
sob o alias SALARIO_ATUAL e o salario reajustado foi mostrado com
o nome SALARIO REAJUSTADO.
Observe que SALARIO_ATUAL é uma palavra só, mas SALARIO
REAJUSTADO contém duas palavras. Neste último caso foi
necessário usar o nome da tabela seguido de ponto e do alias
envolto em aspas para levar em conta que se trata de um nome com
duas palavras. Se não tivessemos utilizado um alias, o título
da última coluna seria SALARIO*1,10, o que, certamente, não é
muito conveniente.
Pode-se usar alias também para os nomes de tabelas, o que
mostraremos em exercícios posteriores.
3)A palavra reservada AS designando um nome substituto é
optativa e pode ser dispensada, como fizemos para o campo
calculado.
4)Você pode usar quaisquer expressões aritméticas válidas. A
precedência natural dos operadores aritméticos + - * / pode ser
alterada utilizando parênteses. Algumas implementações aceitam
o operador MOD ou (%) para obter-se o resto de uma divisão.
Para mais um exemplo com expressões, suponhamos que a empresa, além do salário, pague um prêmio fixo de R$ 50,00 a todos os funcionários e que haja um desconto único de 10% de INSS também para todos os funcionários. Não há outros descontos. Vamos calcular todos os valores para obter o Líquido a pagar.
Exemplo 10: SELECT MATRICULA,NOME,SALARIO SALARIO_MENSAL, "R$50.00" PREMIO, SALARIO+50 BRUTO, (SALARIO+50)*0.10 INSS, (SALARIO+50)-(SALARIO+50)*0.10 LIQUIDO FROM FUNCIONARIOS
Resultado : MATRICULA NOME SALARIO_MENSAL PREMIO BRUTO INSS LIQUIDO --------- ---------------- -------------- ------- ---------- ------- --------- 1 Fernando Bom 5.500,00 50.00 5.550,00 555,00 4.995,00 2 Adriano Segundo 780,00 50.00 830,00 83,00 747,00 3 Mauricio Bello 700,00 50.00 750,00 75,00 675,00 4 Sebastião Bola 400,00 50,00 450,00 45,00 405,00 5 Firmino Pinto 800,00 50,00 850,00 85,00 765,00 6 Carla Lerda 500,00 50.00 550,00 55,00 495,00 7 Madalena Bolha 750,00 50,00 800.00 80,00 720,00
Comentários :
1) Se a expressão da última coluna fosse (SALARIO+50)*0.90,
obteríamos o mesmo resultado.
2) Isto é apenas um exercício. Naturalmente que o cálculo de
uma Folha de Pagamento real é bem mais complexo.
Olhando a 'Folha de Pagamento' acima, o responsável pelo pagamento do pessoal iria, sem dúvida, desejar uma coluna adicional contendo o acumulado da Folha que, ao final lhe informaria o Total a ser dispendido. Ele iria querer ver algo assim :
MATRICULA NOME SALARIO_MENSAL PREMIO BRUTO INSS LIQUIDO ACUMULADO --------- ---------------- -------------- ------- -------- ------ -------- ---------- 1 Fernando Bom 5.500,00 50.00 5.550,00 555,00 4.995,00 4.995,00 2 Adriano Segundo 780,00 50.00 830,00 83,00 747,00 5.742,00 3 Mauricio Bello 700,00 50.00 750,00 75,00 675,00 6.417,00 4 Sebastião Bola 400,00 50,00 450,00 45,00 405,00 6.822,00 5 Firmino Pinto 800,00 50,00 850,00 85,00 765,00 7.587,00 6 Carla Lerda 500,00 50.00 550,00 55,00 495,00 8.082,00 7 Madalena Bolha 750,00 50,00 800.00 80,00 720,00 8.802,00
Esta determinação não é possível com um único
comando SQL Local já que vc só pode utilizar em um campo
calculado, valores do registro atual, ou seja, ao processar a
matrícula 4 o SQL só 'vê' os campos do Sebastião Bola, não
existe um campo totalizador para guardar o acumulado da Folha.
Este é um problema similar ao da Conta Corrente bancária em que
se deseja, lançar, dia a dia, os valores de Crédito e Débido e
mostrar, a cada dia, o saldo da conta.
Além da possibilidade evidente de se prover a tabela com um
campo persistente para o Saldo, existem algumas soluções que
fogem ao escopo deste trabalho. O exemplo só foi mostrado para
alertar para uma das limitações mais comuns de campos
calculados e que pode conduzir a resultados erroneos.
O SQL local tem as seguintes funções :
Funções Aritméticas agregativas (agregate functions) : SUM(), para totalizar todos os valores numéricos em uma coluna; AVG(), para calcular a média aritmética de todos os valores numéricos não nulos em uma coluna MIN(), para determinar o valor mínimo em uma coluna MAX(), para determinar o valor máximo em uma coluna COUNT(), para fornecer a contagem do número de valores em uma coluna, satisfazendo a um determinado critério. Os parâmetros podem conter expressões, por ex: SUM( alhos + bugalhos ), onde alhos e bugalhos são campos numéricos SUM( Campo1 * 10 ), onde Campo1 é numérico
Funções de String (string functions) : UPPER(), coloca toda a string em maiúsculas LOWER(), coloca toda a string em minúsculas TRIM(), para remover as repetições de um caracter especificado da esquerda, da direita ou de ambos os lados da string SUBSTRING() para criar uma substring de uma string. Exemplo : SELECT SUBSTRING(NOME FROM 1 TO 4) FROM CLIENTES
Função de Data : EXTRACT () para extrair o ano, o mês, o dia, a hora, os minutose ou os segundos de um campo tipo date ou datetime. Exemplo : SELECT EXTRACT(YEAR FROM DATA_ENTRADA) FROM FUNCIONARIOS
Exemplo 11: SELECT COUNT(*)NUM_DE_FUNCIONARIOS FROM FUNCIONARIOS
Resultado : NUM_DE_FUNCIONARIOS ------------------- 7
Pode-se usar qualquer coluna que o resultado será o mesmo.
Exemplo 12: SELECT COUNT(MATRICULA)NUM_DE_FUNCIONARIOS FROM FUNCIONARIOS
Resultado : NUM_DE_FUNCIONARIOS ------------------- 7
Exemplo 13: SELECT COUNT(*)NUM_DE_FUNCIONARIOS FROM FUNCIONARIOS WHERE SALARIO > 600
Resultado : NUM_DE_FUNCIONARIOS ------------------- 5
Exemplo 14: SELECT SUM(SALARIO)TOTAL_DE_SALARIOS, MAX(SALARIO) MAIOR_SALARIO, MIN(SALARIO) MENOR SALARIO, AVG(SALARIO) SALARIO_MEDIO FROM FUNCIONARIOS
Resultado : TOTAL_DE_SALARIOS MAIOR_SALARIO MENOR SALARIO SALARIO_MEDIO ----------------- ------------- ------------- ------------- 9.430,00 5.500,00 400,00 1.347,14 Comentários : 1) A função AVG() desconsidera valores nulos acaso existentes.
Min() e Max() podem ser usadas também com campos de caracteres.
Exemplo 15: SELECT MIN(NOME), MAX(NOME) FROM FUNCIONARIOS
Resultado : MIN OF NOME MAX OF NOME ----------------- -------------- Adriano Segundo Sebastião Bola
Para o exemplo já utilizado anteriormente (Exemplo 10) em que a empresa, além do salário, paga um prêmio fixo de R$ 50,00 a todos os funcionários e há um desconto único de 10% de INSS, vamos calcular o Total Liquido a pagar.
Exemplo 16: SELECT SUM((SALARIO+50)*0.90)LIQUIDO FROM FUNCIONARIOS
Resultado : LIQUIDO ------------------- 8.802,00
Para analisar junções, ou seja, consultas abrangendo
mais de uma tabela, vamos utilizar 3 tabelas : Clientes,
Mercadorias, Vendas. Estas tabelas fazem parte do sistema de
contrôle de uma loja de artigos de informática.
OBS:
1)As tabelas, montadas em Paradox 7, estão anexas a este
trabalho e são mostradas a seguir.
2)Novamente, os valores das tabelas não tem nenhum compromisso
com a realidade, servem apenas para exemplo.
3)As implementações mais elaboradas de SQL têm
comandos próprios tais como JOIN, e suas qualificações OUTER,
INNER, RIGHT, LEFT etc... Estes comandos não serão tratados
aquí por não serem suportados pelo SQL-92. Por ser um trabalho
essencialmente prático, não nos ocuparemos tampouco dos
conceitos da teoria dos conjuntos por trá destas designações.
SELECT * FROM CLIENTES
COD_C NOME SEXO ENDERECO BAIRRO TELEFONE RENDA_MENSAL ----- ------------ ---- --------------- -------- ---------- ------------ 1 MARCOS POSTO M R. Tortuosa,22 ALEGRIA 765-4321 5.500,00 2 FERNANDO NANDO M R. da Lama, 31 TRISTEZA 775-7771 500,00 3 MAURICIO MAURO M Tv. Transversa,11 BELEZA 765-3333 2.200,00 4 MARINA MAURA F R. Descida, 27 ALEGRIA 765-8765 3.000,00 5 MIRIAM SOLO F Ld.do Escorrega,2 TRISTEZA 777-7272 1.000,00 6 THEREZA RIOS F R. da Praça, 15 BELEZA 787-7877 3.000,00
SELECT * FROM MERCADORIAS
COD_M DESCRICAO ESTOQUE CUSTO PRECO ----- ----------------------- ------- --------- -------- 1 PC PENTIUM II-200 5 1.100,00 1.450,00 2 PC PENTIUM I-166 12 900,00 1.100,00 3 FAX-MODEM US.R. 6 140,00 180,00 4 IMPRESSORA HP 690 3 400,00 600,00 5 KIT MULTIMIDIA ADVEN 4 190,00 220,00 6 PC PENTINUM II-233 2 1.300,00 1.600,00
SELECT * FROM VENDAS
COD_C COD_M DATA QUANTIDADE ----- ----- -------- ---------- 3 1 15/10/98 1 2 2 15/10/98 2 1 5 16/10/98 1 1 4 16/10/98 1 5 5 18/10/98 2 4 5 20/10/98 1
O responsável pelo Estoque de nossa empresa fez a seguinte consulta ao nosso BD.
Exemplo 17: SELECT V.COD_M, DESCRICAO,ESTOQUE ESTOQUE_INICIAL, SUM(QUANTIDADE) VENDAS, ESTOQUE-SUM(QUANTIDADE) ESTOQUE_ATUAL FROM VENDAS V, MERCADORIAS M WHERE V.COD_M = M.COD_M GROUP BY DESCRICAO,V.COD_M, ESTOQUE
Resultado : COD_M DESCRICAO ESTOQUE_INICIAL VENDAS ESTOQUE_ATUAL ----- --------- --------------- ------ ------------- 4 IMPRESSORA HP 690 3 1 2 5 KIT MULTIMIDIA ADVEN 4 4 0 2 PC PENTIUM I-166 12 2 10 1 PC PENTIUM II-200 5 1 4 Comentários : 1) Observe o uso de aliases para tabelas (M para Mercadorias e V para Vendas) e de colunas (ESTOQUE_INICIAL) para ESTOQUES e ESTOQUE_ATUAL para o campo calculado. Na realidade, só utilizamos o alias de tabelas para o campo COD_M(Código da Mercadoria), já que este é o único campo em que os nomes coincidem. Por uma questão de padronização, poderíamos estender o alias a todos os campos. 2) Observe que o resultado (conjunto resultado) está classificado pela DESCRIÇÃO. Quando se tem a cláusula Group By sem a cláusula Order By,o resultado é classificado na mesma ordem do Group By. 3) Na realidade queríamos a query agrupada apenas pela DESCRICAO, mas as regras nos obrigam a colocar todos os campos 'simples' na cláusula GROUP BY. No caso atual isto é indiferente pois para cada DESCRICAO só existe um valor para COD_M e ESTOQUE. A coisa pode ser bem diferente se não for este o caso... 4) Vale repetir, ESTOQUE_ATUAL é um campo virtual (não pertence a nenhuma tabela). Assim, não há nenhuma modificação em dados permanentes sendo este campo, apenas informativo, ajudando, por exemplo, na previsão de novas compras. Outro aspecto sôbre campos virtuais que as vezes conduz a resultados errôneos é o fato de que só podemos utilizar valores (permanentes) do registro atual na geração dos valores deste campo. Na tabela de vendas acima, podemos ver que há 3 vendas do Kit Multimídia (dias 16, 18 e 20/10/98).Não teríamos, por exemplo, como demonstrar dia a dia, o estoque remanescente deste item, por não termos como transmitir o saldo calculado de um lançamento para o lançamento seguinte. (Veja, no exemplo seguinte mais uma limitação deste tipo de campo).
O responsável pelo Depto. Financeiro iria preferir a seguinte consulta :
Exemplo 18: SELECT V.COD_M, DESCRICAO, SUM(QUANTIDADE*PRECO) R$_VENDAS, SUM(QUANTIDADE*CUSTO) R$_CUSTOS, SUM(QUANTIDADE*PRECO)-SUM(QUANTIDADE*CUSTO) R$_LUCRO, SUM(QUANTIDADE*(PRECO-CUSTO))*100/SUM(QUANTIDADE*CUSTO) LUCRO_PERC FROM VENDAS V, MERCADORIAS M WHERE M.COD_M =V.COD_M GROUP BY DESCRICAO, V.COD_M
Resultado : COD_M DESCRICAO R$_VENDAS R$_CUSTOS R$_LUCRO LUCRO_PERC ----- --------- --------- --------- -------- ------------------ 4 IMPRESSORA HP 690 600,00 400,00 200,00 50 5 KIT MULTIMIDIA ADVEN 880,00 760,00 120,00 15,7894736842105 2 PC PENTIUM I-166 2.200,00 1.800,00 400,00 22,2222222222222 1 PC PENTIUM II-200 1.450,00 1.100,00 350,00 31,8181818181818 Comentários : 1) Não se assuste com a aparente complexidade das fórmulas matemáticas. Lucro nada mais é (pelo menos aquí neste exercício, onde não estamos preocupados com uma apuração real de lucro que certamente envolve outros fatores)que a diferença Vendas-Custo,Lucro Percentual é esta diferença expressa como percentagem do Custo. Seria mais fácil se pudëssemos fazer R$_VENDAS-R$_CUSTOS p/ calcular o Lucro,mas não podemos,já que estes campos são virtuais. e não podemos usar valores de campos virtuais para calcular valores de outros campos. 2) Observe também o imenso trem de casas decimais em alguns valores de lucro percentual. Não temos, no SQL Local, nenhuma forma prática de formatar estes valores. Todas as linguagens de programação possuem componentes (ou funções)que permitem fazer a formatação,resolvendo este tipo de problema.
O Setor de Vendas, por outro lado, estaria interessado em dados para fazer o faturamento das vendas realizadas e poderia fazer a seguinte consulta :
Exemplo 18: SELECT C.NOME,C.TELEFONE,SUM(V.QUANTIDADE*M.PRECO) VALOR_COMPRAS,C.RENDA_MENSAL FROM VENDAS V, MERCADORIAS M, CLIENTES C WHERE C.COD_C = V.COD_C AND V.COD_M = M.COD_M GROUP BY C.NOME,C.TELEFONE, C.RENDA_MENSAL
Resultado : NOME TELEFONE VALOR_COMPRAS RENDA_MENSAL ---- -------- ------------- ------------ FERNANDO NANDO 775-7771 2.200,00 500,00 MARCOS POSTO 765-4321 820,00 5.500,00 MARINA MAURA 765-8765 220,00 3.000,00 MAURICIO MAURO 765-3333 1.450,00 2.200,00 MIRIAM SOLO 777-7272 440,00 1.000,00 Comentários : 1)Utilizamos dados de 3 tabelas diferentes. 2)O valor da RENDA_MENSAL é apenas informativo. Talvez para orientar o Setor de Vendas sôbre possíveis pedidos de parcelamento 3)O telefone, bom... O telefone deve ser para marcar o dia da cobrança...
Podemos usar o resultado de uma subquery como argumento para a condição em uma cláusula Where. Note que o valor retornado pela subquery deve ser único, senão ocorrerá um erro...
Queremos verificar as vendas de kits multimidia. Não sabemos (ou não queremos usar ) o código da mercadoria.
Exemplo 19: SELECT V.DATA,V.COD_M,M.DESCRICAO,V.QUANTIDADE FROM VENDAS V, MERCADORIAS M WHERE V.COD_M = M.COD_M AND V.COD_M = (SELECT COD_M FROM MERCADORIAS WHERE DESCRICAO = "KIT MULTIMIDIA ADVEN" )
Resultado : DATA COD_M DESCRICAO QUANTIDADE ---- ----- --------- ---------- 16/10/98 5 KIT MULTIMIDIA ADVEN 1 18/10/98 5 KIT MULTIMIDIA ADVEN 2 20/10/98 5 KIT MULTIMIDIA ADVEN 1
Quando não sabemos a descrição completa, podemos usar LIKE (desde que a subquery retorne um único valor).
Exemplo 20: SELECT V.DATA,V.COD_M,M.DESCRICAO,V.QUANTIDADE FROM VENDAS V, MERCADORIAS M WHERE V.COD_M = M.COD_M AND V.COD_M = (SELECT COD_M FROM MERCADORIAS WHERE DESCRICAO LIKE "IMPRESSORA%" )
Resultado : DATA COD_M DESCRICAO QUANTIDADE ---- ----- --------- ---------- 16/10/98 4 IMPRESSORA HP 690 1 Só há um item começando com IMPRESSORA.
O próximo comando provoca um erro pois o retorno da subquery não é único.
Exemplo 21 : SELECT V.DATA,V.COD_M,M.DESCRICAO,V.QUANTIDADE FROM VENDAS V, MERCADORIAS M WHERE V.COD_M = M.COD_M AND V.COD_M = (SELECT COD_M FROM MERCADORIAS WHERE DESCRICAO LIKE "PC%" ) Provoca o seguinte erro : "Single row subquery produced more than one row..."