Apostila Do Select SQL

Embed Size (px)

Citation preview

  • 5/21/2018 Apostila Do Select SQL

    1/13

    LINGUAGEM ESTRUTURADA DE CONSULTA

    O programador que chega no Visual FoxPro , vindo de linguagens padrao Xbase (Foxpro 2.x,Clipper , Dbase, etc) acaba encontrando na linguagem SQL , uma grande aliada, e apesar dos

    comandos serem diferentes do Xbase , existe muita coisa que continuar igual, porque oVisual FoxPro possui linguagem SQL de forma nativa, basta abrir a Janela de comandos esair digitando instrues SQL. Nos tempos de Clipper por exemplo, o programador estavaacostumado a fazer "perguntas" para o Banco de dados usando os comandos USE , SETFILTER , SET RELATION , SET ORDER , BROWSE etc. Tudo isto continua exatamenteigual no Visual FoxPro. Com a linguagem SQL voc tambm faz tudo isto, e mais , comresultados bem melhores, e com a vantagem que j estaremos nos preparando paradesenvolver uma aplicao cliente/servidor.

    O que devemos observar, e nunca confundir, SQL a linguagem , com SQL SERVER , que um Banco de Dados da Microsoft. Mas nao nos preocupemos com este Banco de dados SQL

    agora, porque dentro do Visual FoxPro, no SQL nativo, existe o "assistente de upsizing doSql Server" que vai se encarregar de criar um Banco de dados SQL Server , aonde podemosmover dados locais (DBF) para um servidor remoto, transformando as tabelas de base local(DBF) e suas visualizaes locais, em tabelas de base remota e visualizaes remota,migrando assim, de um aplicativo local (Prg, Dbf) para um aplicativo cliente/servidor (Web).

    Alguns conceitos , como o de "abrir"uma tabela de dados, iro mudar o conceito, porquepassaremos a nos preocupar com um servidor remoto, e em se falando de servidor remoto,falaremos ento em fazer "conexo" com uma fonte de dados.

    J fomos muito alm do que pretendamos nesta breve introduo.

    Voltando a uma aplicao local, vamos nos deter na instruo SQL SELECT ou SELECTSQL, que muito poderosa, e podemos sair escrevendo ela dentro da janela de comandos.

    Select a legitima instruo de consulta, e ao escrever precisamos : definir qual a perguntadeve ser respondida pelo banco de dados (tabela) e o que que queremos saber do banco(tabela).

    Exemplificando: Uma pergunta do tipo : Qual minha lista de devedores ? , no seria nadacriativo, e seria bem melhor se fosse perguntado por exemplo, "Preciso saber nome,

    endereo, e quando cada um dos meus clientes est devendo, ordenado por data dovencimento"

    Tudo o que precisamos aprender a perguntar ao banco de dados (tabela). Nos exemplos quecolocarei, deve ficam bem claro que sempre existiro diversas formas para se atingir umobjetivo, e vamos usar a que mais fcil parecer ao aluno.

    A partir daqui, imaginemos que existe uma tabela de nome "CLIENTES" com os camposque passaremos a nos referenciar nos exemplos.

    Ento vamos a parte bem prtica: Perguntando e Respondendo :

    . Quero todos os dados de todos os clientes, no importa a ordem.

  • 5/21/2018 Apostila Do Select SQL

    2/13

    Resposta

    Select * from clientes

    O sinal * indica todos (todos os campos da tabela)

    J que nenhuma filtragem foi solicitada, todos os registros da tabela serao mostrados.

    Antes mesmo de continuar, interessante lembrar que os comandos VFP podem ser escritosem mais de uma linha, e o sinal ; (Ponto e virgula) deve ser colocado ao final de uma linha,indicando que o comando continua na prxima linha.

    .Quero o nome de todos os clientes, independente de ordem.

    Resposta

    Select nome as nome_do_cliente from clientes

    Nome o prprio nome do campo, nome_do_cliente , como eu quero que saia no cabealhoda consulta.

    .Quero o nome da empresa e o nome do contato, de todos os clientes, ordenado por nome daempresa.

    Resposta

    Select nome_empresa , nome_contato from clientes order by 1

    By 1 significa que vai sair em ordem pelo campo 1 da lista (Nome_empresa)

    . Quero a regiao , nome da empresa e o nome do contato, de todos os clientes, ordenados porregiao e pelo nome da empresa.

    Resposta

    Select regiao,nome_da_empresa,nome_contato;

    from clientes order by regiao,nome_da_empresa

    Na clausula order by, se precisarmos ordenar por mais campos, basta escreve- los, separandopor virgulas, e evidentemente que estar uma ordem dentro da outra. No exemplo acima, osnomes das empresas estaro em ordem crescente dentro de cada regiao.

    .Quero a lista de todas as regioes onde tenho meus clientes.

    Esta pergunta vai nos fazer usar de uma clausula GROUP BY. Acontece que existem muitosregistros que sero mostrados e tem uma grande quantidade de regioes diferentes.

    Resposta

  • 5/21/2018 Apostila Do Select SQL

    3/13

    Select regiao from clientes group by regiao

    E tudo isto por que: porque queremos que o nome de uma regiao saia apenas uma vez, e poristo, usamos o agrupamento (Group By)

    . Quero saber quantos clientes eu tenho em cada regiao.

    Esta j uma pergunta mais completa.

    Resposta

    Select regiao , count(regiao) as contagem;from clientes group by regiao

    Count(regiao) : est indicando que eu quero uma contagem (Funcao Count())

    As contagem : foi necessrio para identificar um cabealho para este total que ser mostrado.

    . Quero saber o nome da empresa e nome do contato de todos os clientes , ordenado pelonome da empresa.

    Resposta

    Select nome_empresa, nome_contato;

    from clientes order by 1

    . Quero saber quantos clientes eu tenho por regiao, porm como podem existir regioes em"branco", nao quero que aparea aquele cabealho "regiao sem nome", e para mostrar umabusca mais clara, escrevo:

    Resposta

    Select IIF(not empty()regiao), regiao,;

    "regiao nao encontrada") as regiao , count(regiao);as contagem from clientes group by regiao

    A funo IIF possibilita que se o campo "regiao" no estiver vazio, utilizamos o seu

    contedo, seno colocamos um "regiao no informada" no registro.

    . Agora umaa pergunta mais complexa. Na tabela clientes, existe um outro campo chamadoValor_maior , indicando de quanto foi o valor do maior pedido efetuado por um cliente.Quero entao saber qual foi o valor mais alto j pedido em cada regiao, da regiao com valormais baixo, at a regiao com valor mais alto.

    Resposta

    Select regiao, max(valor_maior) as maior_pedido;from clientes group by regiao order by 2

    Sairo as regioes, e dentro das regioes, cfe solicitado, em ordem do menor valor ao maior

  • 5/21/2018 Apostila Do Select SQL

    4/13

    valor.

    . Mas no exemplo anterior, veio muita coisa, e eu quero montar o meu ranking top 10, com as10 regioes que tiverem os maiores valores de pedidos, da regiao com o maior pedido para aregiao com menor pedido (ou seja, ordem decrescente)

    Resposta

    Select top 10 regiao, max(valor_maior);as maior_pedido from clientes;group by regiao order by 2 desc

    Ficou tudo mais ou menos igual, apenas que a clausula TOP 10 indica que serao mostrados os10 maiores.

    Importante: Quando voc usa a clausula TOP , "obrigatrio" definir uma "ordem" (order

    by)

    . Agora, uma coisa mais complexa ainda. A empresa vai fazer uma promoo para 20% dasregioes de maior valor de pedido feito, e veja como solicito isto.

    Resposta

    Select top 20 percent regiao,;

    max(valor_maior) as maior_pedido;from clientes group by regiao order by 2 desc

    Neste caso, como existe a clausula percent , o 20 significa 20 %

    . Preciso saber o nome diz meus clientes na regiao de Santa maria

    Resposta

    Select nome_empresa from clientes ;where regiao = "Santa maria"

    A clausula Where, faz a filtragem mostrando apenas clientes que seja da regiao citada (Santa

    Maria, no caso). Alm de "Santa Maria tambm quero, "Santa Rosa"

    Resposta

    Select nome_empresa, regiao from clientes;where regiao = "Santa Maria" or ;regiao = "Santa Rosa"

    A nica diferena em relaao a consulta anterior, que esta pede duas regioes, ento na

    filtragem uso a clausula OR ( OU )

  • 5/21/2018 Apostila Do Select SQL

    5/13

    . A empresa precisa agora da lista com os nomes dos clientes em 5 regioes : "sp", "rj" , "pa" ,"pr" e "ms" .

    Resposta

    Select nome_empresa , regiao from clientes;where inlist (regiao,"sp","rj","pa","pr","ms")

    Acrescentou-se a clausula INLIST e nomeamos as regioes solicitadas.

    Importante: Com criatividade, dentro de um prg, podemos informar quais as 5 regioes, jogarpara variveis rg1,rg2,rg3.rg4,rg5 e escrever o select assim :

    Select nome_empresa , regiao from clientes;where inlist(regiao,rg1,rg2,rg3,rg4,rg5)

    Mais ..

    No caso INLIST (regiao "sp","rj","pa","pr","ms") e se esta lista fosse maior !! Neste caso usea funo INLIST() , voc diz para ela qual o campo e qual a lista de valores que voce deseja

    procurar, e estar resolvido.

    . A empresa est fazendo uma grande promoo para os clientes, e quer presentear aquelesque estiverem entre os registros 10 e 20 do cadastro.

    Resposta

    Select recno(), nome_empresa from clientes;

    where between(recno(),10,20)

    Estamos ento usando a funo RECNO() , e na filtragem colocandoBETWEEN(recno(),10,20) indicando que devem ser mostrados apenas os clientes entre oregistro 10 e o 20 ( 10,11,12,13,14,15,16,17,18,19,20)

    . Agora a empresa quer saber o nome dos clientes, cujo nome da empresa comea com a letra"S"

    RespostaSelect * from clientes ;where nome_empresa like "S%"

    Apenas foi usada na filtragem a condio LIKE, indicando que s vai mostrar, donome_empresa , os que iniciarem por "S" (% significa que os restantes caracteres do nomenao importa)

    . Agora, a empresa vai convocar uma reunio com todos os gerentes dos clientes. Precisaento uma listagem com o nome dos gerentes e o telefone.

    Resposta

  • 5/21/2018 Apostila Do Select SQL

    6/13

    Select gerente, telefone from clientes;where upper(cargo) like "%gerente%"

    Veja :

    No campo "cargo" vai estar gravado por exemplo, "Gerente de vendas" ou "Scio gerente defilial" , exemplos apenas, e neste caso o LIKE "%gerente%" vai pegar qualquer tipo deocorrncia, desde que em algum lugar esteja gravado a palavra "gerente" (Por isso o sinal de% antes e depois )

    Upper(cargo) significa que ele vai passar o contedo do campo CARGo para maisculo, paraevitar problemas nas comparaes, maisculas e minsculas.

    . A empresa quer saber: Listar as regioes onde tem mais de 2 clientes, desconsiderandoaqueles clientes que no possuem regiao informada.

    Resposta

    Select regiao, count(*) as contagem;

    from clientes;

    where not empty(regiao);

    group by regiao having contagem > = 3

    Veja :

    Count(*) joga o resultado para uma varivel CONTAGEM e no final a clausula HAVING fazum filtro, especificando que a contagem precisa ser > ou igual a 3.

    . A empresa quer ver a lista de clientes, datas de pedidos de cada um, ordenada pelo nome daempresa e pela data do pedido.

    Resposta

    Select clientes.nome_empresa,;pedidos.data_pedido;

    from clientes,pedidos;

    where clientes.codigo_cliente = pedidos.codigo_cliente;order by clientes.nome_empresa,pedidos.data_pedido

    Existem duas tabelas ; a tabela Clientes e a Pedidos e sero consultadas em paralelo. A tabelapedidos possui os pedidos todos, e a clientes os nomes dos clientes.

    Na clausula from , preciso referenciar as duas tabelas.

    Na clausula WHERE , voc estabeleceu que as duas tabelas vo correr juntas, sendo unidaspelo campo codigo_cliente que existe nas duas tabelas.

    E o order By , especifica que a ordem de amostragem ser por nome do cliente, e dentro decada cliente por data do pedido.

  • 5/21/2018 Apostila Do Select SQL

    7/13

    . A empresa precisa ver a lista de clientes e datas de pedidos de cada um (duas tabelas)ordenada pelo nome da empresa e pela data do pedido.

    Resposta

    Select a.nome_empresa, b.data_pedido;from clientes a , pedidos b;

    where a.codigo_cliente = b.codigo_cliente;order by nome_empresa,data_pedido

    S o que mudou foi o fato de terem sido associadas a cada tabela, as letras A e B , A paraClientes e B para Pedidos. (A e B so conhecidos como local alis)

    . Agora a empresa precisa ver a lista de clientes e datas de pedidos de cada um, ordenada pelonome da empresa e pela data do pedido.

    Resposta

    Select clientes.nome_empresa,pedidos.data_pedido;

    from clientes;

    inner join pedidos on clientes.codigo_cliente = pedidos.codigo_cliente;

    order by clientes.nome_empresa,pedidos.data_pedido

    Sobre o INNER JOIN

    Uma nova forma de fazer JUNO entre tabelas. Temos duas tabelas , uma est a esquerda(clientes) e outra do lado direito (pedidos). Com o INNER JOIN , vamos saber, quais osregistros do lado esquerdo que encontraram pelo menos 1 registro equivalente do lado direito.Assim sendo, s veremos os clientes que efetivaram algum pedido.

    . A empresa quer a mesma coisa do exemplo anterior, s que agora, esta lista tem que trazertodo mundo, mesmo que o cliente no tenha feito pedido algum.

    Resposta

    Select clientes.nome_cliente, pedidos.data_pedido;

    from clientes;LEFT JOIN pedidos;on clientes.codigo_cliente = pedidos.codigo_cliente;order by clientes.nome_empresa,pedidos.data_pedido

    Veja :

    Substituindo INNER JOIN pelo LEFT JOIN , faz com que a consulta retorne todos osregistros do lado esquerdo da juno, independente de encontrar registro equivalente do ladodireito.

    . Agora a empresa quer saber a quantidade total de pedidos atendidos por cada funcionrio. Alista tem que ser ordenada pelo nome dos funcionrios. Vamos colocar outra tabela na jogada,

  • 5/21/2018 Apostila Do Select SQL

    8/13

    a tabela "funcionrios"

    Resposta

    Select funcionarios.primeiro_nome_do_funcionario ,;

    count(pedidos.codigo_cliente) as qtde_total_pedidos;from pedidos;inner join funcionarios ;

    on funcionarios.codigo_funcionario = pedidos.codigo_funcionario;group by funcionarios.primeiro_nome_do_funcionario;order by funcionarios.primeiro_nome_do_funcionario

    muito fcil de entender, porque todas as clausulas j foram praticadas.

    . Bem, nesta lista no aparecem todos os funcionrios, est faltando alguns, e a empresa querque apaream.

    Ento:

    Resposta

    Select funcionarios.primeiro_nome_do_funcionario,;

    count(pedidos,codigo_cliente) as qtde_total_pedidos ;

    from pedidos;

    right join funcionarios on funcionarios.codigo_funcionario;= pedidos.codigo_funcionario;

    group by primeiro_nome_do_funcionario;

    order by primeiro_nome_do_funcionario

    Falamos a alguns exerccios atrs, que LEFT JOIN traz todos os registros do lado esquerdoda relao, lembra. Pois ento, tambm temos o RIGHT JOIN, que traz todos os registros dolado direito da relao, ou seja , neste caso, traz todos os funcionrios , independente deexistir algum pedido por ele atendido ou no. No exerccio anterior, aqueles que noatenderam a nenhum pedido, ficaram de fora.

    . Agora a empresa quer saber quem so os funcionrios que no atenderam nenhum pedido.

    RespostaSelect funcionarios.primeiro_nome_do_funcionario;from funcionarios;

    where funcionarios.codigo_funcionario not IN ;(select funcionarios.codigo_funcionario from pedidos)

    Agora voc vai aprender a usar sub-queries (Sub consulta). A essncia da pergunta : da listade funcionrios, quem que no tem nenhum pedido atendido !

    Fazemos ento o select na tabela funcionarios, filtrando por somente aqueles que o

    codigo_funcionario nao estiver na tabela pedidos.

  • 5/21/2018 Apostila Do Select SQL

    9/13

    Inicialmente a sub consulta executada, para se saber quais sao os codigo_funcionario natabela de pedidos, e em seguida executada a consulta na tabela de funcionarios, procurandosomente os codigo_funcionario que no esto no resultado da primeira consulta.

    Quantas linhas de comando voc ter ganho em clipper, para fazer uma consulta destas !

    Algumas dezenas com certeza.

    . A empresa agora quer fazer um agrado para os funcionarios mais fiis e produtivos. Paraisto, precisa saber quem so os funcionarios que atenderam mais de 100 pedidos ou queforam contratados de 1993 at hoje.

    Resposta

    Select alltrim(funcionarios.primeiro_nome_do_funcionario);+" "+funcionarios.ultimo_nome_do_funcionario;

    from pedidos;inner join funcionarios on ;

    funcionarios.codigo_funcionario = ;pedidos.codigo_funcionario ;

    group by funcionarios.primeiro_nome_do_funcionario;

    having count(pedidos.codigo_pedido) > 100 ;

    union;

    select alltrim(primeiro_nome_do_funcionario)+;

    " "+ultimo_nome_do_funcionario from;funcionarios;

    where year(data_admissao) > = 1993

    Parece que a coisa complicou, mas no bem assim. Verifique, temos duas grandescondicoes :

    1 : Funcionrios que atenderam mais de 100 pedidos. Voc j sabe fazer isso atravs dohaving e do count() ( A novidade aqui, que o count() pode ser usado diretamente junto dohaving)

    2 : Funcionrios que foram contratados de 1993 at o dia atual. ( A nica novidade aqui ouso da funo YEAR() , para ver o ano da data da contratacao.

    A grande novidade est na clausula UNION. Esta clausula UNE consultas. Ento o ideal criar a primeira consulta, e testaremos. Funcionou? Criamos a segunda consulta, e testamos ,funcionou?

    Unimos entao as duas com a clausula UNION. Ela junta os registros das duas consultas, edespreza registros repetidos ( Neste caso, o funcionrio que atende aos dois critrios) Sequiser tambm os registros repetidos, basta usar UNION ALL.

    Como um a consulta agregada a outra, ser necessrio que ambas produzam uma estruturaigual, caso contrrio gerado um erro.

    . Agora a empresa quer uma listagem, uma nica listagem, com nome de todos os

  • 5/21/2018 Apostila Do Select SQL

    10/13

    funcionrios e contatos de clientes, para mandar um carto de natal no final do ano.

    Resposta

    Select padr(primeiro_nome_do_funcionario,30," ") ;

    as nome , "funcionario" as tipo ;from funcionarios;union;

    select nome_do_contato, "cliente" as tipo;from clientes;order by 2 , 1

    A diferena que neste caso, somaremos registros de duas tabelas diferentes.

    J falamos que a estrutura das tabelas tem de ser iguais. Ento o campoprimeiro_nome_do_cliente na tabela funcionrios do tipo Caracter, tamanho 10. J o campo

    nome_do_contato na tabela clientes tambm do tipo Caracter, s que o tamanho 30, eagora como fica!

    Lembre-se de uma regra : A primeira consulta que dita a estrutura das demais em umainstruo com UNIONs ( isso mesmo, podemos ter vrias, vrias consultas ligadas porvrios UNIONs). Ento precisamos dar um jeito no campo primeiro_nome_do_funcionario ,

    para que ele fique igual ao nome_do_contato. Para isto basta usar a funcao PADR() quepreenche um string com um numero X de um determinado caractere, no nosso caso,preenchemos com espaos vazios, at que a string alcance o tamanho 30. Ok, agora elas jso compatveis.

    A clausula ORDER BY aqui s pode ser usada com o numero das colunas na lista, e no pelonome dos campos, pois podem ser completamente diferentes entre as consultas.

    Daqui para frente, quem quiser se especializar ainda mais, use o HELP do VFP.

    21 de Agosto de 2003Dinarte Incio Kreutz

    Utilizao de datas no MySQLO artigo abaixo objetiva facilitar o entendimento do manuseio de datas dentro dos padres

    brasileiros, um dos maiores problemas na manipulao de dados. Para isso tomamos comobase o SGBD MySQL 5.

    Para manipularmos dados do tipo DATA, podemos definir a coluna como DATE,DATETIMEou TIMESTAMP, sendo que suas principais caractersticas so:

    # DATE esta no formato AAAA-MM-DD# DATETIME esta no formato AAAA-MM-DD HH:MM:SS# TIMESTAMP esta no formato AAAAMMDDHHMMSS

  • 5/21/2018 Apostila Do Select SQL

    11/13

    Apesar das datas do tipo DATETIMEe TIMESTAMPutilizarem hora, minuto e segundo,podemos utilizar seu contedo somente com a data. Para isso, utiliza-se a funoDATE_FORMAT(date,format) , que transforma a data apresentada para o formato desejado.Tambm podemos utilizar essa funo para colocar qualquer tipo de data no formato maisadequado para nossa aplicao, como por exemplo no formato "DD/MM/AAAA".

    As datas so armazenadas no formato norte-americano e, para obtermos o resultado noformato Brasileiro, devemos utilizar a funo acima:

    Ex: se for necessrio apresentar a data de uma determinada transao no formato

    "DD/MM/AAAA" deve-se fazer o comando de seleo com a seguinte sintaxe:SELECT DATE_FORMAT(nome_da_coluna_com_a_data, '%d/%m/%Y')

    FROM nome_da_tabela;

    Ateno especial deve ser dada s colunas definidas como "TIMESTAMP", pois nelas ficamdepositados data e horrio de atualizao da linha na tabela, isto : quando feita umamudana em qualquer dado de uma linha da tabela o dado da coluna definida como

    TIMESTAMP atualizado com o momento atual.

    Para melhor entender o uso dos tipos de data no MySQL, apresentamos a seguir comandosque demonstram o resultado de datas formatadas:

    SELECT * FROM FORMATODATA;SELECT DATE_FORMAT(DT_nida como

    72347a emada pcorrta. PTj 242.25 0 TD D / 12 Tf 0.1188 Tc (DD/M48SELECT DATE_F 0 TD /F30665

  • 5/21/2018 Apostila Do Select SQL

    12/13

    SELECT DAYOFWEEK('1998-02-03');

    Para obtermos o dia do ano utilizamos a funo DAYOFYEAR(date)

    Ex.|

    SELECT DAYOFYEAR(CURDATE());

    Para obtermos o momento atual, utilizamos a funo NOW()ou SYSDATE()

    Ex.|

    SELECT NOW(), SYSDATE();

    SELECT dentro de SELECT

    Uma coisa muito interessante que a maioria dos SGBDs atuais no mercado tem uma propriedade

    que permite realizar um SELECT dentro de outro SELECT. Vamos imaginar a seguinte situao,temos os seguintes registros de uma tabela:

    Codigo Tipo Status

    1 1 1

    2 2 3

    3 2 4

    4 1 2

    5 2 5

    Agora voc deseja agrupar esses itens pelo Tipo exibindo o ultimo registro. Quando usamos oGROUP BY o SELECT agrupa todos os itens mais pegando sempre o primeiro registro.

    Ex: SELECT * FROM tabela GROUP BY Tipo

    Resultados:

    Codigo Tipo Status

    1 1 1

    2 2 3

    Mesmo que voc utilize o ORDER BY dentro deste SELECT ele no ira funcionar (SELECT * FROM

    tabela GROUP BY Tipo ORDER BY Codigo).

    Como queremos o ultimo registro vamos ento usar um SELECT dentro de outro SELECT, vamos

    preceder da seguinte maneira, primeiro vamos criar um SELECT de maneira que os dados venhamem ordem decrescente em seguida utilizando a tcnica para criar um SELECT dentro de outro evamos agrup-los pelo Tipo.

    Ex: SELECT * FROM (SELECT * FROM tabela ORDER BY Cdigo DESC) AS a GROUP BY a.Tipo

    Resultados:

    Cdigo Tipo Status

    4 1 2

    5 2 5

  • 5/21/2018 Apostila Do Select SQL

    13/13

    Podemos usar o SELECT dentro de outro SELECT para inmeras solues, basta apenas surgir oportunidade.

    http://cristianosalomao.blogspot.com.br/2007/09/select-

    dentro-de-select.html