Desvendando o SQL - Parte IV - Consultas
Continuamos nossa série de artigos que tem como objetivo mostrar um pouco sobre a linguagem SQL. Nos 3 primeiros artigos procuramos mostrar o que é o SQL, como criar um banco de dados e as primeiras estruturas necessárias para podermos detalhar a linguagem. Os links para os antigos anteriores estão no final do artigo. E dentre as variações e comandos existentes hoje vamos começar a trabalhar com o SELECT. Esse comando é usando para selecionar ou consultar os dados em uma determinada tabela.
No último artigo deixei um desafio pra ser resolvido de acordo com tudo que vimos, acredito que tenha conseguido, caso não tenham disponibilizo nesse artigo o script com a solução do desafio.
USANDO O SELECT
De que serviriam os dados armazenados em um banco de dados se não pudessem ser consultados? De modo geral, para absolutamente nada. Esses dados tem alguma funcionalidade, se eles foram inseridos no BD, em algum momento serão trazidos de volta, é nesse momento que são realizadas as consultas, e na linguagem SQL o comando que realiza esse trabalho é o SELECT.
Lembra que no segundo artigo, Desvendando o SQL - Parte II usamos uma consulta pra ver os dados da tabela de produtos? Usamos a sintaxe abaixo:
SELECT * FROM TBPRODUTO
Pois essa é uma forma simples de fazer uma consulta, de uma forma simplificada a sintaxe do comando é o seguinte:
SELECT <lista de campos>
FROM <lista de tabelas>
WHERE <condições da consulta>
GROUP BY <campos de agrupamentos>
HAVING <condições do agrupamento>
ORDER BY <ordenação dos campos>
Cláusula SELECT
Na cláusula SELECT determina que campos vão aparecer no retorno da consulta, quando colocamos um “*” como na consulta acima, não estamos especificando campos nenhum e sim dizendo ao interpretador do banco que traga todos os campos da, ou das tabelas. Pode-se colocar como campos de retorno, além dos campos normais existentes, funções de agregação (mostradas em Desvendando o SQL - Parte I - Introdução , concatená-los, ser o retorno de outra consulta, ser valores fixos, dentre outros, sempre separados por vírgula.
Ex: SELECT CD_PRODUTO, ‘Teste’, COUNT(*)
Na relação dos campos podemos também utilizar DISTINCT, que determina que as repetições, caso existam, da relação de campos não façam parte da consulta. E também o TOP que retornará somente o número de registro que foi determinado, se usado junto com a opção PERCENT, o valor inserido vai representar o percentual de registros existentes.
Cláusula FROM
Na cláusula FROM fica a, ou as, tabelas que farão parte da consulta, ou ainda outro select pode ser usado com uma tabela, mais isso é no futuro. Quando temos mais de uma tabela devemos fazer a relação entre elas para que os dados se combinem, existem de modo geral duas maneiras de fazer essa combinação, usando a condição que liga as tabela na cláusula WHERE ou usando os operadores JOIN e suas variações, particularmente gosto mais de usar os operadores por me darem maior liberdade, mas com ambos o resultado será o mesmo.
Condição na cláusula WHERE
Usando essa forma as tabelas são colocadas na cláusula FROM, separadas por virgulas, FROM , , . E as condições que ligam as tabelas serão incluídas na clausula WHERE.
Usando Operadores Join
Usando esses operadores as tabelas continuam sendo colocadas no FROM e as condições que as ligam também ficarão nessa cláusula
...FROM <tabela1> INNER JOIN <tabela2> ON <tabela1>.campo = <tabela2>.campo
Existem algumas opções de JOIN disponíveis, INNER JOIN, LEFT JOIN, RIGHT JOIN E CROSS JOIN, existem outro mais trabalharemos com esses por enquanto.
- O INNER JOIN retorna somente os registros que atendam a condição de singularidade dos campos
.campo = .campo, somente os registros onde o campo da tabela1 for igual ao campo da tabela2; - O LEFT JOIN retorna todos os registros da tabela da esquerda mesmo que não existam na tabela da direita;
- O RIGHT JOIN retorna todos os registros da tabela da direita mesmo que não existam na tabela da esquerda;
- O CROSS JOIN retorna todos os registros das duas tabelas montando um produto cartesiano de ambas.
Usando Alias
Quando utilizamos somente uma tabela na consulta colocar os nomes dos campos é uma tarefa fácil, pois não é preciso determinar de que tabela virá, mas quando temos duas ou mais tabelas essa tarefa pode se tornar um pouco mais complicada, já imaginou se o nome colocado em uma tabela foi TABELAPRODUTOACABADOS? Mais duas ou três tabelas com nomes parecidos? Ao determinar que campos retornassem teríamos que colocar TABELAPRODUTOACABADOS.campo1, TABELAPRODUTOACABADOS.campo2, TABELAPRODUTOACABADOS.campo3 e fazer isso para todos os campos que fosse preciso, já imaginou o tamanho que o script ficaria? Principalmente em códigos muito extensos.
Por conta disso os padrões do SQL aceitam que sejam colocadas alias ou apelido na relação de tabelas, facilitando a sua visualização, então nosso script acima ficaria de forma mais amigável e organizado. E esses apelidos podem ser usados ao longo de todo o script.
SELECT TPD.CAMPO1, TPD.CAMPO2, TPD.CAMPO3
FROM TABELAPRODUTOACABADOS
AS TPD INNER JOIN TABELAPRODUTOVENDIDOS AS
TPV ON TPD.CAMPO = TPV.CAMPO
Cláusula WHERE
Na cláusula WHERE que entram as condições de restrição da consulta, uma condição geralmente é montada restringindo o valor de um campo usando Operadores Relacionais (Desvendando o SQL - Parte I - Introdução) como, por exemplo:
- Campo = 1 – retorna valores iguais a 1;
- Campo <> 0 – retorna valores diferentes de zero;
- Campo >= 100 – retorna valores maiores ou iguais a 100;
- Campo in (valor1, valor2, valor3) – retorna todos os valores entre parênteses;
- Campo between valor1 and valor2 – usa o intervalo entre valor1 e valor2 incluindo-os;
- Campo like ‘valor%’ – retorna tudo que comece com ‘valor’;
- Campo1 = 1 AND Campo2 <> 2 – retorna os registros que atendam ambas as condições;
- Campo1 = 1 OR Campo2 <> 2 – retorna os registros que atenda pelo menos umas das condições;
- NOT(Campo1 = 1) é o mesmo que Campo1 <> 1 – retorna os registros que negam a condição. Se usando com o IN, por exemplo, Campo NOT IN (valor1, valor2, valor3), retorna os registros que sejam diferentes aos valores entre parênteses, é uma condição de negação;
Clausula GROUP BY
Quando precisamos fazer um agrupamento de determinado campos usamos a clausula GROUP BY, geralmente usamos em conjunto com as funções de agregação usadas no SELECT. Como observação todos os campos que foram usados no SELECT, excluindo o campo da agregação devem está listados no GROUP BY ou o interpretador vai gerar um erro.
Clausula HAVING
Esta clausula funciona como um WHERE do GROUP BY. Quando precisamos inserir uma condição no resultado do agrupamento usamos a clausula HAVING, em geral podem ser usadas as mesmas condições do WHERE.
Clausula ORDER BY
Quando uma consulta é gerada em geral ela fica ordenada pela chave primária, que por padrão já é um índice da tabela, em seguida o próximo campo da sequencia e o outro e assim até o final. Mas em determinadas situações precisamos ordenar o retorno da consulta por colunas específicas e ai entra essa clausula. Os campos serão ordenados na ordem que forem listados. Caso desejem uma ordenação inversa usa-se o DESC após o nome do campo.
ORDER BY Campo1, Campo2, Campo3 Desc
Retorno das Consultas
Existe um painel de retorno das consultas que é mostrado abaixo das consultas, esse retorno pode ser mostrado em Grid (Ctrl + D), em texto (Ctrl + T) usado nos scripts abaixo e salvo em um arquivo (Ctrl + Shift + F) que cria um arquivo com extensão rpt, mas pode ser aberto em qualquer editor de texto.
Exemplos
Explicadas as clausulas do SELECT, vamos agora mostrar alguns exemplos de consultas, começamos das mais simples e vamos dificultando ao longo dos exemplos.
1. Todos os Registros da tabela de categorias;
SELECT *
FROM TBCATEGORIA
CD_CATEGORIA DESC_CATEGORIA
------------ ------------------------------
1 Bebidas
2 Cereais
3 Lacticínios
4 Massas
5 Enlatados
(5 linha(s) afetadas)
2. Os 10 primeiros registros da tabela de produtos;
SELECT TOP 10 *
FROM TBPRODUTO
CD_PRODUTO CD_REFERENCIA
DESC_PRODUTO
CD_CATEGORIA ST_PRODUTO NR_SERIE
----------- -------------
-------------------------------------------------- ------------ ----------
---------------
1 1001 Whisky 08 Anos 1 A NS110011
2 1002 Whisky 12 Anos 1 A NS210021
3 1003 Vinho
1 A NS310031
4 2001 Arroz Branco 2 A NS420012
5 2002 Feijão Carioca 2 A NS520022
6 3001 Leite Longa Vida 3 A NS630013
7 3002 Leite Longa Vida Desnatado 3 A NS730023
8 4010 Macarrão Parafuso 4 A NS840104
9 4020 Macarrão Talharim 4 A NS940204
10 6100 Pêssego em Calda 5 A NS1061005
(10 linha(s) afetadas)
3. Retorna 10% do total de registro da tabela de produtos;
SELECT TOP 10 PERCENT *
FROM TBPRODUTO
CD_PRODUTO CD_REFERENCIA
DESC_PRODUTO
CD_CATEGORIA ST_PRODUTO NR_SERIE
----------- -------------
-------------------------------------------------- ------------ ----------
---------------
1 1001 Whisky 08 Anos 1 A NS110011
2 1002 Whisky 12 Anos 1 A NS210021
(2 linha(s) afetadas)
4. Criação de um campo na consulta e retornando somente alguns campos da tabela de unidades;
SELECT 'TABELA DE UNIDADES' AS
TABELA, SGL_UNIDADE, DESC_UNIDADE, QTD_PADRAO
FROM TBUNIDADE
TABELA SGL_UNIDADE
DESC_UNIDADE
QTD_PADRAO
------------------ -----------
--------------------------------------------------
---------------------------------------
TABELA DE UNIDADES UN
Unidade 1.00
TABELA DE UNIDADES GR
Grama
1000.00
TABELA DE UNIDADES KG
Quilo
1.00
TABELA DE UNIDADES LT Litro
1.00
TABELA DE UNIDADES PCT
Pacote
1.00
TABELA DE UNIDADES CX12
Caixa 12 Unidades 1.00
TABELA DE UNIDADES CX24 Caixa 24 Unidades 1.00
(7 linha(s) afetadas)
5. Inserindo uma condição pra retorno;
SELECT *
FROM TBUNIDADE
WHERE QTD_PADRAO = 1
CD_UNIDADE SGL_UNIDADE
DESC_UNIDADE QTD_PADRAO
----------- -----------
--------------------------------------------------
---------------------------------------
1 UN Unidade
1.00
3 KG Quilo 1.00
4 LT Litro
1.00
5 PCT Pacote
1.00
6 CX12 Caixa 12 Unidades 1.00
7 CX24 Caixa 24 Unidades 1.00
(6 linha(s) afetadas)
6. Ordenando uma consulta
SELECT CD_REFERENCIA, DESC_PRODUTO
FROM TBPRODUTO
WHERE ST_PRODUTO <> 'A'
ORDER BY DESC_PRODUTO
CD_REFERENCIA DESC_PRODUTO
------------- --------------------------------------------------
(0 linha(s) afetadas)
7. Agrupando na tabela subcategorias pelo código da categoria;
SELECT CD_CATEGORIA, COUNT(*) AS QTD
FROM TBSUBCATEGORIA
GROUP BY CD_CATEGORIA
CD_CATEGORIA QTD
------------ -----------
1 6
2 2
3 2
5 2
6 5
(5 linha(s) afetadas)
8. Relacionando as tabelas de produto e subcategoria
SELECT P.CD_PRODUTO, P.DESC_PRODUTO, S.CD_SUB, S.DESC_SUB
FROM
TBPRODUTO AS P INNER JOIN
TBSUBCATEGORIA AS S ON S.CD_SUB = P.CD_SUB
CD_PRODUTO DESC_PRODUTO
CD_SUB DESC_SUB
----------- --------------------------------------------------
----------- ------------------
1 Whisky 08 Anos 6 Whisky
2 Whisky 12 Anos 6 Whisky
3 Vinho
3 Vinhos
4 Arroz Branco 7 Grãos
5 Feijão Carioca 7 Grãos
6 Leite Longa Vida 8 Cereal Diet
7 Leite Longa Vida Desnatado 8 Cereal Diet
8 Macarrão Parafuso 12 Conservas
9 Macarrão Talharim 12 Conservas
10 Pêssego em Calda 10 Queijo
11 Ervilha
11 Doces
12 Milho Verde 11 Doces
(12 linha(s) afetadas)
9. Relacionando as tabelas de produto, subcategoria e categoria;
SELECT P.DESC_PRODUTO, C.DESC_CATEGORIA, S.DESC_SUB
FROM
TBPRODUTO AS P INNER JOIN
TBSUBCATEGORIA AS S ON S.CD_SUB = P.CD_SUB INNER JOIN
TBCATEGORIA AS C ON C.CD_CATEGORIA = S.CD_CATEGORIA
WHERE
C.DESC_CATEGORIA = 'BEBIDAS'
DESC_PRODUTO
DESC_CATEGORIA
DESC_SUB
--------------------------------------------------
------------------------------
--------------------------------------------------
Whisky 08 Anos Bebidas Whisky
Whisky 12 Anos
Bebidas
Whisky
Vinho
Bebidas
Vinhos
(3 linha(s) afetadas)
10. Relacionando as tabelas de estoque, produto e unidade;
SELECT P.CD_REFERENCIA, P.DESC_PRODUTO, E.QTD_ESTOQUE, U.SGL_UNIDADE, E.VLR_UNITARIO
FROM
TBESTOQUE AS E INNER JOIN
TBPRODUTO AS P ON E.CD_PRODUTO = P.CD_PRODUTO INNER JOIN
TBUNIDADE AS U ON U.CD_UNIDADE = E.CD_UNIDADE
CD_REFERENCIA DESC_PRODUTO
QTD_ESTOQUE
SGL_UNIDADE VLR_UNITARIO
------------- --------------------------------------------------
--------------------------------------- ----------- -------------
1001 Whisky 08 Anos
4.0000
CX12 60.00
1002 Whisky 12 Anos
3.0000
CX12 110.00
1003 Vinho
4.0000
CX12 40.00
2001 Arroz Branco
61.0000
KG 6.50
2002 Feijão Carioca
46.0000
KG 8.70
3001 Leite Longa
Vida
6.0000
CX12 4.30
3002 Leite Longa Vida
Desnatado
4.0000
CX12 4.70
4010 Macarrão
Parafuso
21.0000
KG 2.20
4020 Macarrão Talharim 16.0000 KG 3.50
6100 Pêssego em
Calda
3.0000
CX12 7.50
6200 Ervilha 2.0000 CX24 2.35
6300 Milho Verde
2.0000
CX24 2.48
(12 linha(s) afetadas)
11. Retirando as repetições dos registros e usando todos os dados da tabela da esquerda;
SELECT DISTINCT U.DESC_UNIDADE
FROM
TBUNIDADE AS U LEFT JOIN
TBESTOQUE AS E ON U.CD_UNIDADE = E.CD_UNIDADE
DESC_UNIDADE
--------------------------------------------------
Caixa 12 Unidades
Caixa 24 Unidades
Grama
Litro
Pacote
Quilo
Unidade
(7 linha(s) afetadas)
12. Retirando as repetições dos registros e usando todos os dados da tabela da direita;
SELECT DISTINCT U.DESC_UNIDADE
FROM
TBUNIDADE AS U RIGHT JOIN
TBESTOQUE AS E ON U.CD_UNIDADE = E.CD_UNIDADE
DESC_UNIDADE
--------------------------------------------------
Caixa 12 Unidades
Caixa 24 Unidades
Quilo
(3 linha(s) afetadas)
13. Relacionando as tabelas de categoria e subcategoria;
SELECT *
FROM
TBCATEGORIA AS C INNER JOIN
TBSUBCATEGORIA AS S ON C.CD_CATEGORIA = S.CD_CATEGORIA
CD_CATEGORIA DESC_CATEGORIA CD_SUB DESC_SUB
CD_CATEGORIA
------------ ------------------------------ -----------
-------------------------------------------------- ------------
1 Bebidas 1 Refrigerante 1
1 Bebidas 2 Refrigerante Diet 1
1 Bebidas 3 Vinhos 1
1 Bebidas 4 Água Mineral 1
1 Bebidas 5 Aguardente 1
1 Bebidas 6 Whisky 1
2 Cereais 7 Grãos 2
2 Cereais 8 Cereal Diet 2
3 Lacticínios 9 Leite 3
3 Lacticínios 10 Queijo 3
5 Enlatados 11 Doces 5
5 Enlatados 12 Conservas 5
6 Carnes 13 Sem Categoria Definida 6
6 Carnes 14 Bovinos 6
6 Carnes 15 Aves
6
6 Carnes 16 Suinos 6
6 Carnes 17 Caprinos 6
(17 linha(s) afetadas)
14. Usando o cross join, gera um produto catersiando com todos os registros das duas tabelas usadas
SELECT *
FROM
TBCATEGORIA AS C CROSS JOIN
TBSUBCATEGORIA AS S
CD_CATEGORIA DESC_CATEGORIA CD_SUB DESC_SUB
CD_CATEGORIA
------------ ------------------------------ -----------
-------------------------------------------------- ------------
1 Bebidas 1 Refrigerante 1
1 Bebidas 2 Refrigerante Diet 1
1 Bebidas 3 Vinhos 1
1 Bebidas 4 Água Mineral 1
1 Bebidas 5 Aguardente 1
1 Bebidas 6 Whisky 1
1 Bebidas 7 Grãos 2
1 Bebidas 8 Cereal Diet 2
1 Bebidas 9 Leite 3
1 Bebidas 10 Queijo 3
1 Bebidas 11 Doces 5
1 Bebidas 12 Conservas 5
1 Bebidas 13 Sem Categoria Definida 6
1 Bebidas 14 Bovinos 6
1 Bebidas 15 Aves 6
1 Bebidas 16 Suinos 6
1 Bebidas 17
Caprinos 6
2 Cereais 1 Refrigerante 1
2 Cereais 2 Refrigerante Diet 1
2 Cereais 3 Vinhos 1
2 Cereais 4 Água Mineral 1
2 Cereais 5 Aguardente 1
2 Cereais 6 Whisky 1
2 Cereais 7 Grãos 2
2 Cereais 8 Cereal Diet 2
2 Cereais 9 Leite 3
2 Cereais 10 Queijo 3
2 Cereais 11 Doces 5
2 Cereais 12 Conservas 5
2 Cereais 13 Sem Categoria Definida 6
2 Cereais 14 Bovinos 6
2 Cereais 15 Aves
6
2 Cereais 16 Suinos 6
2 Cereais 17 Caprinos 6
3 Lacticínios 1 Refrigerante 1
3 Lacticínios 2 Refrigerante Diet 1
3 Lacticínios 3 Vinhos 1
3 Lacticínios 4 Água Mineral 1
3 Lacticínios 5 Aguardente 1
3 Lacticínios 6 Whisky 1
3 Lacticínios 7 Grãos 2
3 Lacticínios 8 Cereal Diet 2
3 Lacticínios 9 Leite 3
...
6 Carnes 14 Bovinos 6
6 Carnes 15 Aves
6
6 Carnes 16
Suinos 6
6 Carnes 17 Caprinos 6
(102 linha(s) afetadas)
15. Ordenando a consulta em ordem decrescente;
SELECT CD_PRODUTO, VLR_UNITARIO
FROM TBESTOQUE
ORDER BY VLR_UNITARIO DESC
CD_PRODUTO VLR_UNITARIO
----------- ---------------------------------------
2 110.00
1 60.00
3 40.00
5 8.70
10 7.50
4 6.50
7 4.70
6 4.30
9 3.50
12 2.48
11 2.35
8 2.20
(12 linha(s) afetadas)
16. Usando um relacionando de quatro tabelas, agrupando pelo código e descrição da categoria e incluindo uma condição no agrupamento.
SELECT C.CD_CATEGORIA, C.DESC_CATEGORIA, SUM(E.VLR_UNITARIO) AS SOMA_VALOR
FROM
TBESTOQUE E INNER JOIN
TBPRODUTO P ON P.CD_PRODUTO = E.CD_PRODUTO INNER JOIN
TBSUBCATEGORIA S ON S.CD_SUB = P.CD_SUB INNER JOIN
TBCATEGORIA C ON C.CD_CATEGORIA = S.CD_CATEGORIA
WHERE E.VLR_UNITARIO > 5
GROUP BY C.CD_CATEGORIA, C.DESC_CATEGORIA
HAVING SUM(E.VLR_UNITARIO) > 10
ORDER BY SOMA_VALOR
CD_CATEGORIA DESC_CATEGORIA SOMA_VALOR
------------ ------------------------------
---------------------------------------
2 Cereais 15.20
1 Bebidas 210.00
(2 linha(s) afetadas)
Espero que esse artigo tenha ajudado a conhecer melhor a cláusula SELECT, existe, claro, mais inúmeras variações possíveis e mais outros comandos que podem ser utilizados, que ao longo dos nossos artigos mostraremos. No próximo artigo mostraremos o que são como criar e utilizar uma VIEW. Não percam. E não se esqueçam de opinar, comentar, sugerir, tirar dúvidas, terei prazer em respondê-las.
Grande abraço a todos e até a próxima.
Scripts:
Artigos anteriores:
Desvendando o SQL - Parte II - Criando um Banco de Dados e Tabelas
Desvendando o SQL - Parte III - Alterando Registros
Desvendando o SQL - Parte III - Alterando Registros
Comentários