UFABC UAB TSI T S I A 6B: SQL 2 S A · PDF fileAlgumas consultas necessitam desse tipo de...

Post on 11-Mar-2018

218 views 3 download

Transcript of UFABC UAB TSI T S I A 6B: SQL 2 S A · PDF fileAlgumas consultas necessitam desse tipo de...

francisco.massetto@ufabc.edu.br

UFABC –UAB TSI –

TECNOLOGIA EM SISTEMAS DE

INFORMAÇÃO

AULA 6B: SQL – PARTE 2

SUBCONSULTAS E AGREGAÇÕES

AGENDA

Agrupamento e Agregação de dados

Agrupando resultados de consultas

Somando dados

Contando registros

Média, máximo, mínimo

Subconsultas

Conceitos

Formas de utilização

Quando usar subconsultas?

Criando consultas mais complexas

AGRUPANDO DADOS

Cláusula GROUP BY

Agrupa os dados pelo campo selecionado

Recurso para definirmos totalizações (por exemplo)

Agrupamentos só são realizados após o conjunto de dados ser recuperado

Não pode ser usado antes de uma cláusula WHERE

AGRUPANDO DADOS

mysql> select idProj -> from projFunc -> group by idProj;

+--------+| idProj |+--------+| 1 || 2 |+--------+2 rows in set (0.00 sec)

mysql> select idProj -> from projFunc;

+--------+| idProj |+--------+| 1 || 1 || 2 || 2 || 2 || 2 |+--------+6 rows in set (0.00 sec)

AGREGANDO DADOS

A idéia de agregar é sumarizar alguma informação de um conjunto de registros

Somatórias

Máximos valores

Mínimos valores

Médias

Quantidade de valores

Retirar da responsabilidade da aplicação, uma vez que o SGBD já realiza isso

Algumas consultas necessitam desse tipo de informação como critérios para novas consultas

FUNÇÕES DE AGREGAÇÃO

Max(campo)

Retorna o maior valor do campo dentro de um conjunto

Min(campo)

Retorna o menor valor do campo dentro de um conjunto

Avg(campo)

Retorna o valor médio do campo

Sum(campo)

Retorna a somatória dos valores do campo

Count(campo)

Retorna a quantidade de registros de um campo

USANDO FUNÇÕES DE

AGREGAÇÃO

Contando quantos funcionários há na empresa

mysql> select count(*) from funcionario;+----------+| count(*) |+----------+| 8 |+----------+1 row in set (0.06 sec)

Contando quantos departamentos há na empresa

mysql> select count(*) from departamento;+----------+| count(*) |+----------+| 3 |+----------+1 row in set (0.03 sec)

USANDO AGREGAÇÃO E

AGRUPAMENTOS

Contando quantos funcionários há por projeto

mysql> select idProj, count(idFunc)-> from projFunc group by idProj;

+--------+---------------+| idProj | count(idFunc) |+--------+---------------+| 1 | 2 || 2 | 4 |+--------+---------------+2 rows in set (0.00 sec)

AGRUPANDO, JUNTANDO,

AGREGANDO...

Selecionando os nomes dos projetos que os funcionários trabalham

mysql> select p.descrP, pf.idProj, count(pf.idFunc)-> from projFunc pf inner join projeto p using (idProj)-> group by idProj;

+----------------+--------+------------------+| descrP | idProj | count(pf.idFunc) |+----------------+--------+------------------+| Folha de Pagto | 1 | 2 || Sist. Escolar | 2 | 4 |+----------------+--------+------------------+2 rows in set (0.13 sec)

FILTROS PARA DADOS

AGREGADOS

Cláusula HAVING

Diferença básica entre HAVING e WHERE

Where dados brutos (originados diretamente da tabela ou da view), sem nenhum tratamento

Having dados agregados (somatórias, maiores, menores, contadores)

FILTROS PARA DADOS

AGREGADOS

Filtrando os projetos que possuem mais de 2 funcionários alocados

mysql> select p.descrP, pf.idProj, count(pf.idFunc)-> from projFunc pf inner join projeto p using (idProj)-> group by idProj-> having count(pf.idFunc) > 2;

+---------------+--------+------------------+| descrP | idProj | count(pf.idFunc) |+---------------+--------+------------------+| Sist. Escolar | 2 | 4 |+---------------+--------+------------------+1 row in set (0.06 sec)

AGRUPAMENTOS

Por que utilizar agrupamentos?

Organizar a informação que se quer recuperar

Exemplos de agrupamentos

Totais de vendas por região geográfica

Encontrar vendedores que mais realizaram vendas em um determinado ano

Determinar freqüências de ocorrências de elementos

Número de contas abertas em cada filial de um banco

UM EXEMPLO MAIS

ELABORADO

Este exemplo é um exemplo existente no livro

“Aprendendo SQL – O´Rilley”

E também pode ser obtido pelo endereço

A idéia é que o modelo retrate uma instituição financeira (Banco), onde existem várias agências que oferecem produtos a clientes.

Produtos podem ser Poupança (SAV-savings), financiamentos (LOA –loans), depósitos (CHK–checks), entre outros

A idéia é apenas apresentá-lo para que vocês possam “ler” um modelo de dados já existente e entender também como as consultas foram geradas.

Este exemplo é bastante rico se levarmos em considerações operações de agregações e agrupamentos

UM EXEMPLO MAIS

ELABORADO – AS TABELAS

Account

Uma conta (produto) específico aberto para um cliente em particular

Branch

Uma agência bancária onde uma transação é realizada

Customer

Cliente do banco (pode ser pessoa física ou jurídica)

Business

Cliente pessoa jurídica

Individual

Cliente pessoa física

Department

Departamento do banco

Employee

Funcionário do banco

Officer

O Administrador da pessoa jurídica (pode ter várias)

Product

Um produto oferecido pelo banco (linha de crédito para PJ, hipoteca imobiliária, financiamento de carros)

Product_type

Tipo dos produtos oferecidos (financiamentos, conta bancária, seguros)

Transaction

Uma ocorrência em uma conta bancária

ENTENDENDO O EXEMPLO

Um cliente (customer) é uma entidade que pode ser especializada em duas outras

Pessoa física (individual)

Pessoa jurídica (business)

Todo cliente pessoa jurídica tem um ou mais gerente (que pode ser gerente de apenas 1 pessoa jurídica)

ENTENDENDO O EXEMPLO

Todo produto (product) oferecido pelo banco tem uma categoria (product_type) associado a ela

Além disso todo funcionário (employee) trabalha tem um departamento (department) associado a ele e é gerenciado por outro funcionário (auto-relacionamento)

Adicionalmente, um funcionário está alocado (trabalha) em uma agência

ENTENDENDO O EXEMPLO

O cliente tem uma ou várias contas (account) e toda conta está associada a um produto (product) e a uma agência (branch) onde a conta foi aberta

ENTENDENDO O EXEMPLO

Toda transação (transaction) está associada a uma conta (que pode ser crédito ou débito)

Toda transação também está associada à um empregado (que a efetiva) e a uma agência onde a transação terá efeito (um depósito pode ser feito em uma agência referenciando uma conta de outra agência)

AGRUPAMENTOS POR VÁRIAS

COLUNAS

GROUP BY pode ser utilizado para agrupar dados por várias colunas

Geração de totais e subtotais

No exemplo dos bancos

Caso simples: somar todos os saldos de contas existentes

Elaborando um pouco: somar todos os saldos por tipos de produtos (crédito para pequenas empresas, poupança, etc)

Elaborando mais ainda: somar todos os saldos por tipos de produtos e também por agência

AGRUPAMENTOS POR VÁRIAS

COLUNAS

mysql> select product_cd, open_branch_id, sum(avail_balance) as total -> from account;

+------------+----------------+-----------+| product_cd | open_branch_id | total |+------------+----------------+-----------+| CHK | 2 | 170754.46 |+------------+----------------+-----------+1 row in set (0.03 sec)

mysql> select product_cd, open_branch_id, sum(avail_balance) as total -> from account group by product_cd;

+------------+----------------+----------+| product_cd | open_branch_id | total |+------------+----------------+----------+| BUS | 4 | 9345.55 || CD | 2 | 19500.00 || CHK | 2 | 73008.01 || MM | 3 | 17045.14 || SAV | 2 | 1855.76 || SBL | 3 | 50000.00 |+------------+----------------+----------+6 rows in set (0.08 sec)

Caso 1: somando tudo

Caso 2: agrupando por tipos de produtos

AGRUPAMENTO POR VÁRIAS

COLUNAS

mysql> select product_cd, open_branch_id, sum(avail_balance) as total -> from account group by product_cd, open_branch_id;

+------------+----------------+----------+| product_cd | open_branch_id | total |+------------+----------------+----------+| BUS | 2 | 9345.55 || BUS | 4 | 0.00 || CD | 1 | 11500.00 || CD | 2 | 8000.00 || CHK | 1 | 782.16 || CHK | 2 | 3315.77 || CHK | 3 | 1057.75 || CHK | 4 | 67852.33 || MM | 1 | 14832.64 || MM | 3 | 2212.50 || SAV | 1 | 767.77 || SAV | 2 | 700.00 || SAV | 4 | 387.99 || SBL | 3 | 50000.00 |+------------+----------------+----------+14 rows in set (0.03 sec)

Caso 3: agrupando por produto e por agência em que foi aberto

GERANDO SUMÁRIOS

(ROLLUPS)

Um recurso bastante poderoso oferecido pelo SGBD é a geração automática de sumários (RollUps)

Facilita a recuperação ordenada de informações com as respectivas totalizações automaticamente

Utiliza-se um agrupamento, indicando a necessidade de gerar totalizações

Cláusula WITH ROLLUP adicionada na cláusula GROUP BY

GERANDO SUMÁRIOS

(ROLLUPS)

mysql> select product_cd, open_branch_id, sum(avail_balance) as total -> from account group by product_cd, open_branch_id WITH ROLLUP;

+------------+----------------+-----------+| product_cd | open_branch_id | total |+------------+----------------+-----------+| BUS | 2 | 9345.55 || BUS | 4 | 0.00 || BUS | NULL | 9345.55 || CD | 1 | 11500.00 || CD | 2 | 8000.00 || CD | NULL | 19500.00 || CHK | 1 | 782.16 || CHK | 2 | 3315.77 || CHK | 3 | 1057.75 || CHK | 4 | 67852.33 || CHK | NULL | 73008.01 || MM | 1 | 14832.64 || MM | 3 | 2212.50 || MM | NULL | 17045.14 || SAV | 1 | 767.77 || SAV | 2 | 700.00 || SAV | 4 | 387.99 || SAV | NULL | 1855.76 || SBL | 3 | 50000.00 || SBL | NULL | 50000.00 || NULL | NULL | 170754.46 |+------------+----------------+-----------+21 rows in set (0.01 sec)

Ao invés de deixar a responsabilidade da somatória por conta da aplicação, o SGBD já realiza isso para você. As linhas que contém NULL representam totalizações parciais ou geral

Totais parciais

Total geral

RESUMOS MAIS ELABORADOS

Alguns SGBDs implementam a opção WITH CUBE em suas opções de agrupamento

MySQL não suporta essa opção

WITH ROLLUP

Organiza totais pela ordem dos campos que foram especificados na consulta

Totaliza as agências por tipo de produtos

Totaliza os produtos

WITH CUBE

Totaliza todas as combinações existentes

Totalizaria também todas as agências (independente do tipo de produto)

SUBCONSULTAS

Basicamente uma subconsulta é uma consulta contida em outra instrução SQL

Tipos de resultados

Única linha com única coluna

Única linha e múltiplas colunas

Múltiplas linhas com única coluna

Múltiplas linhas e colunas

Dois tipos de consulta

Subconsultas não correlatas

Subconsultas correlatas

POR QUE SE USAR

SUBCONSULTAS?

Muitas vezes é possível obter o mesmo resultado de uma subconsulta através das cláusulas de filtros (WHERE) indicando igualdades

Mas quando não se souber os valores que devem ser combinados para se fazer o filtro?

Ou não se sabe a quantidade de valores que devem ser comparados para se obter os filtros

Ideal: usar subconsultas

Uma consulta retorna um conjunto de valores que serão combinados (conferidos) com os valores da consulta principal e, então, retornados aos usuários

SITUAÇÃO

Deseja-se, a partir de uma tabela existente, buscar todos os funcionários que são supervisores

mysql> select * from funcionario;+--------+--------------+-------------------+------+------------+---------+---------+| idFunc | nomeF | emailF | sexo | dataAd | idDepto | idSuper |+--------+--------------+-------------------+------+------------+---------+---------+| 1 | Isidro | isidro@ts.com.br | M | 2010-01-01 | 1 | NULL || 2 | Sezefredo | sz@ts.com.br | M | 2010-01-01 | 1 | 1 || 3 | Adamastor | ad@ts.com.br | M | 2010-01-01 | 1 | 1 || 4 | Deosdedite | dd@ts.com.br | M | 2010-01-01 | 1 | 1 || 5 | Energarda | en@ts.com.br | F | 2010-01-01 | 2 | 2 || 6 | Josicleide | josi@ts.com.br | F | 2010-01-01 | 2 | 2 || 7 | Nilsonclecio | outro@terc.com.br | M | 2010-01-01 | 3 | 6 || 8 | Roberval | outro@terc.com.br | M | 2010-01-01 | 3 | 6 || 9 | Cheirosa | outro@terc.com.br | F | 2010-04-30 | 2 | 1 || 10 | Caue | outro@terc.com.br | M | 2010-04-30 | 1 | 1 || 11 | Ermenegildo | emgr@ts.com.br | M | 2010-05-03 | 7 | 1 |+--------+--------------+-------------------+------+------------+---------+---------+11 rows in set (0.01 sec)

COMO FAZER?

1a tentativa – fácil, porém limitada (usando filtros simples)

mysql> select nomeF from funcionario where

idFunc = 1 or idFunc = 2 or idFunc = 6;

+------------+

| nomeF |

+------------+

| Isidro |

| Sezefredo |

| Josicleide |

+------------+

3 rows in set (0.00 sec)

Poblema desta abordagem

Caso surja outro supervisor, a consulta deve ser refeita para incluir na cláusula WHERE o código do novo supervisor

Ou ainda, se o número de identificação do supervisor for alterado

COMO FAZER?

2a tentativa – Subconsultas

Como pensar em subconsultas?

Pense em INTERSECÇÃO, SUBTRAÇÃO de conjuntos ou SUBCONJUNTOS

Conjunto 1 – recuperar os códigos de funcionários e seus respectivos nomes

cujos códigos sejam coincidentes na coluna SUPERVISOR da tabela

COMO FAZER?

+---------+| idSuper |+---------+| NULL || 1 || 1 || 1 || 2 || 2 || 6 || 6 || 1 || 1 || 1 |+---------+

+--------+| idFunc |+--------+| 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || 10 || 11 |+--------+

AS CLÁUSULAS IN E NOT IN

Lembram da teoria dos conjuntos?

Idéia por trás das subconsultas

IN

Indica que os dados que fazem parte do filtro DEVEM fazer parte do conjunto obtido na subconsulta (intersecção com um subconjunto)

NOT IN

Indica que os dados que fazem parte do filtro NÃO DEVEM fazer parte do conjunto obtido na subconsulta (Subtração de conjuntos)

TRANSFORMANDO O RACIOCÍNIO EM

SQL

mysql> select nomeF from funcionario where

-> idFunc IN (select idSuper from funcionario);+------------+| nomeF |+------------+| Isidro || Sezefredo || Josicleide |+------------+3 rows in set (0.00 sec) Esta consulta retorna

um conjunto de ID de

supervisores dos

funcionários

TRANSFORMANDO O RACIOCÍNIO EM

SQL

mysql> select nomeF from funcionario where

-> idFunc IN (select idSuper from funcionario);+------------+| nomeF |+------------+| Isidro || Sezefredo || Josicleide |+------------+3 rows in set (0.00 sec)

O filtro indica todos os

IDs de funcionários

que fazem parte do

conjunto obtido na

subconsulta

ALGUMAS OBSERVAÇÕES

Existem casos em que elementos da query principal não combinam (match) com elementos do conjunto obtido na subconsulta

Operador IN indica que se houver algum elemento na subconsulta, a condição é satisfeita

O operador NOT IN indica que um elemento da query principal não deve ter nenhum correspondente na subconsulta

Todo o conjunto deve ser percorrido

MAIS OBSERVAÇÕES

Ao usar NOT IN, deve-se certificar que os valores retornados pela subconsulta não contenham valores NULL

O SBGD vai igualar o valor do lado esquerdo da expressão com cada valor da subconsulta

Ao igualar o valor com NULL, o resultado é “desconhecido” e, portanto a consulta não resultará no esperado

SITUAÇÃO

Recuperar todos os funcionários que não são supervisores – teoricamente a mesma instrução com uma restrição a mais na 2ª subconsulta

mysql> select nomeF from funcionario -> where idFunc not in (Select distinct idsuper from funcionario);

Empty set (0.00 sec)

mysql> select nomeF from funcionario -> where idFunc in(Select distinct idsuper from funcionario where idSuper is not null)

+--------------+| nomeF |+--------------+| Adamastor || Deosdedite || Energarda || Nilsonclecio || Roberval || Cheirosa || Caue || Ermenegildo |+--------------+8 rows in set (0.00 sec)

O simples fato de uma subconsultaretornar uma única linha com um campo NULL, já pode alterar o resultado de toda a consulta

OPERADOR ALL

Permite realizar operações com TODOS os elementos do subconjuntos

Dessa forma, algum tipo de operação complementar deve ser indicado

=, <>, >, >=, <, <=

OPERADOR ALL

O exemplo anterior também pode ser escrito da seguinte forma:

mysql> select nomeF from funcionario where idFunc <> ALL (Select distinct idsuper from funcionario where idSuper is not

null);

+--------------+| nomeF |+--------------+| Adamastor || Deosdedite || Energarda || Nilsonclecio || Roberval || Cheirosa || Caue || Ermenegildo |+--------------+8 rows in set (0.00 sec)

OPERADOR ANY

Da mesma forma que o ALL, o ANY também compara elementos da consulta inicial com os elementos da subconsulta

Operadores complementares também fazem-se necessários

Assim que, pelo menos 1 elemento da subconsulta satisfaz a condição, ele já faz parte do resultado

Observação

NOT IN <> ALL

IN = ANY

SUBCONSULTAS COM MAIS DE

UM CAMPO

Subconsultas podem retornar mais de um campo

A ordem de filtro dos campos que serão referenciados na subconsulta deverá ser exatamente a mesma dos campos retornados pela subconsulta

Muito cuidado com isso!!!

SUBCONSULTAS CORRELATAS

Subconsultas vistas até agora são ditas Não Correlatas

A subconsulta é executada independentemente

Inclusive é uma forma de depuração das informações obtidas

Subconsultas correlatas possuem elementos dependentes da instrução-contêiner

Ou seja, campos da consulta principal fazem parte do critério de filtro da subconsulta

COMO FUNCIONA UMA

SUBCONSULTA CORRELATA?

Ao invés de ser executada uma única vez, antes da execução da consulta-contêiner, a subconsulta correlata é executada para cada linha-candidata

Linhas que podem ser incluídas no resultado final

É a consulta que mais exige acessos ao disco.

Portanto de menor eficiência.

Seu uso deve ser muito bem planejado, pois, em geral é possível recuperar boa parte do que se pretende usando subconsultas não correlatas

Mesmo que tabelas diferentes façam parte da subconsulta correlata

Situação: no exemplo das contas bancárias, como recuperar os códigos dos clientes que possuem saldo entre $5000 e $10000?

SUBCONSULTAS CORRELATAS

1o passo – buscar as somatórias das contas de todos os clientes

Select sum(a.avail_balance) from account a

2o passo – buscar de um determinado cliente

Select sum(a.avail_balance) from account a

where a.cust_id = ???

Porém deve-se recuperar TODOS os clientes que tiverem conta e, finalmente filtrar o valor final pelo critério escolhido

SUBCONSULTAS CORRELATAS

mysql> select c.cust_id, c.cust_type_cd, c.city-> from customer c-> where (select sum(a.avail_balance)-> from account a-> where a.cust_id = c.cust_id)-> between 5000 and 10000;

+---------+--------------+------------+| cust_id | cust_type_cd | city |+---------+--------------+------------+| 4 | I | Waltham || 7 | I | Wilmington || 11 | B | Wilmington |+---------+--------------+------------+3 rows in set (0.09 sec)

A presença do campo

c.cust_id tanto na

consulta quanto na

subconsulta torna-a

correlata

OPERADOR EXISTS

Muito utilizado em consultas correlatas

Simplesmente retorna a quantidade de registros encontrados

0, 1 ou mais registros

O conteúdo dos dados recuperados não é importante

Verifica apenas se o resultado existe ou não

EXEMPLO

É possível recuperar o número da conta e o saldo disponível das contas que possuem transação no dia 03 de maio de 2010?

1o passo – recuperar as transações que possuem determinado código de conta

Se existir alguma transação para esta conta, mostra o número da conta e o saldo existente

Como fazer?

SUBCONSULTAS CORRELATAS

mysql> select a.account_id, a.product_cd, a.cust_id, a.avail_balance-> from account a-> where EXISTS-> (select 1 from-> transaction t-> where t.account_id = a.account_id-> and t.txn_date='2008-09-22');

Empty set (0.00 sec)

mysql> select a.account_id, a.product_cd, a.cust_id, a.avail_balance-> from account a-> where EXISTS-> (select 1 from-> transaction t-> where t.account_id = a.account_id-> and t.txn_date='2010-05-03');

+------------+------------+---------+---------------+| account_id | product_cd | cust_id | avail_balance |+------------+------------+---------+---------------+| 1 | CHK | 1 | 1057.75 |+------------+------------+---------+---------------+1 row in set (0.00 sec)

A subconsulta deve

retornar algo, não

importando os valores

“Select 1” indica que se houver alguma coisa, retorna

apenas um valor „1‟. Em geral, quando usa-se EXISTS,

usa-se „select 1‟ ou „select *‟ para indicar que existem

valores