You are on page 1of 57

SQL Consultas Aninhadas e Agregao

Profa. Sandra de Amo Capitulo 5 Livro Texto Database Management Systems Ramakrishnan - Gehrke

Exerccios

Variantes da consulta D o nome dos marinheiros que reservaram barcos vermelhos Variantes equivalentes da consulta D o nome dos estudantes do primeiro perodo que esto matriculados em alguma disciplina ministrada pela Profa. Maria Amlia

D os nomes dos marinheiros que reservaram Sailors barcos vermelhos Resposta Sid Snome Status Idade
N1

SELECT S.Snome FROM Sailors S WHERE S.Sid IN (SELECT R.Sid FROM Reservas R WHERE R.Bid IN (SELECT B.Bid FROM Barcos B WHERE B.Cor = Vermelho))

N3 N6 22 22 31 31 64

22 29 31 32 58 64 71 74 85 95 Sid 22 22 22 22 31 31 31 64 64 74

N1 N2 N3 N4 N5 N6 N7 N6 N8 N9

7 1 8 8 10 7 10 9 3 3

45 33 55,5 25,5 35 35 16 35 25,5 63,5

Reservas
Bid Dia 101 D1 102 D1 103 D3 104 D4 102 D5 103 D6 104 D7 101 D8
102 103 D9 D9

Barcos
Bid BN Cor 101 A1 Azul 102 A1 Verm 103 104 A2 Verde A3 Verm

102 104

D os nomes dos marinheiros que NO reservaram barcos vermelhos Sailors N2


SELECT S.Snome FROM Sailors S WHERE S.Sid NOT IN (SELECT R.Sid FROM Reservas R WHERE R.Bid IN (SELECT B.Bid FROM Barcos B WHERE B.Cor = Vermelho))
N4 N5 N7 N6 N8 N9 22 22 31 31 64 102 104 Resposta
Sid Snome Status Idade 22 N1 7 45 29 N2 1 33 8 55,5 31 N3 8 32 N4 25,5 58 N5 35 10 35 64 N6 7 71 N7 10 16 N6 74 9 35 85 N8 3 25,5 95 N9 3 63,5

Reservas
Dia 22 101 D1 22 102 D1 22 103 D3 22 104 D4 31 102 D5 31 103 D6 31 104 D7 64 101 D8 64 102 D9 74 103 D9 Sid Bid

Barcos
Bid BN Cor 101 A1 Azul 102 A1 Verm 103 A2 Verde 104 A3 Verm

D os nomes dos marinheiros que reservaram Sailors barcos no vermelhos Resposta Sid Snome Status Idade
SELECT S.Snome FROM Sailors S WHERE S.Sid IN (SELECT R.Sid FROM Reservas R WHERE R.Bid NOT IN (SELECT B.Bid FROM Barcos B WHERE B.Cor = Vermelho))
N1 N3 N6 N6
22 22 31 64 74
22 29 31 32 58 64 71 74 85 95 N1 N2 N3 N4 N5 N6 N7 N6 N8 N9 7 1 8 8 10 7 10 9 3 3 45 33 55,5 25,5 35 35 16 35 25,5 63,5

Reservas
Sid Bid Dia 22 101 D1 22 102 D1 22 103 D3 22 104 D4 31 102 D5 31 103 D6 31 104 D7 64 101 D8 64 74 102 103 D9 D9

Barcos
Bid 101 102 103 104 BN A1 A1 A2 A3 Cor

102 104

Azul Verm Verde Verm

D os nomes dos marinheiros que no reservaram barcos no vermelhos Sailors


Resposta

SELECT S.Snome FROM Sailors S WHERE S.Sid NOT IN (SELECT R.Sid FROM Reservas R WHERE R.Bid NOT IN (SELECT B.Bid FROM Barcos B WHERE B.Cor = Vermelho))

N2 N4 N5 N7 N8 N9 22 22 31 64 74 102 104

Sid Snome Status Idade 45 22 N1 7 1 29 N2 33 31 N3 55,5 8 25,5 8 32 N4 10 35 58 N5 64 N6 7 35 16 71 N7 10 74 N6 9 35 85 N8 25,5 3 95 N9 3 63,5

Reservas
Sid Bid Dia 22 101 D1 22 102 D1 22 103 D3 22 104 D4 31 102 D5 31 103 D6 31 104 D7 64 101 D8 64 74 102 103 D9 D9

Barcos
Bid 101 102 103 104 BN A1 A1 A2 A3 Cor

Azul Verm Verde Verm

D o nome dos estudantes do primeiro perodo que esto matriculados em alguma disciplina ministrada pela Profa. Maria Amlia
VARIANTE 1 : Sem subconsultas aninhadas
SELECT E.ENOME FROM ESTUDANTE E, MATRICULADO M, DISCIPLINA D, PROF P WHERE E.PERIODO = 1 AND E.ENUM = M.ENUM AND M.DID = D.DID AND D.PID = P.PID AND P.PNOME = Maria Amlia

D o nome dos estudantes do primeiro perodo que esto matriculados em alguma disciplina ministrada pela Profa. Maria Amlia
VARIANTE 2 : com um nvel de aninhamento SELECT E.ENOME FROM ESTUDANTE WHERE E.PERIODO = 1 AND E.NUM IN (SELECT M.ENUM FROM MATRICULADO M, DISCIPLINA D, PROF P WHERE M.DID = D.DID AND D.PID = P.PID AND P.PNOME = Maria Amlia)

D o nome dos estudantes do primeiro perodo que esto matriculados em alguma disciplina ministrada pela Profa. Maria Amlia
VARIANTE 3 : com dois nveis de aninhamento
SELECT E.ENOME FROM ESTUDANTE WHERE E.PERIODO = 1 AND E.NUM IN (SELECT M.ENUM FROM MATRICULADO M WHERE M.DID IN (SELECT D.DID FROM DISCIPLINA D, PROF P WHERE D.PID = P.PID AND P.PNOME = Maria Amlia))

D o nome dos estudantes do primeiro perodo que esto matriculados em alguma disciplina ministrada pela Profa. Maria Amlia
VARIANTE 4 : com trs nveis de aninhamento
SELECT E.ENOME FROM ESTUDANTE WHERE E.PERIODO = 1 AND E.NUM IN (SELECT M.ENUM FROM MATRICULADO M WHERE M.DID IN (SELECT D.DID FROM DISCIPLINA D WHERE D.PID IN (SELECT P.PID FROM PROF P WHERE P.PNOME = Maria Amlia)))

Condies do WHERE em consultas aninhadas

A IN (R: Resultado de subconsulta)

Verdadeiro se o valor do atributo A est em R


Verdadeiro se o valor do atributo A no est em R Verdadeiro se R no vazio Verdadeiro se R vazio

A NOT IN (R: Resultado de subconsulta)

EXISTS (R: Resultado de subconsulta)

NOT EXISTS (R: Resultado de subconsulta)

Exemplo
Encontre nome de marinheiros que reservaram o barco 103

SELECT S.Snome FROM Sailors S WHERE EXISTS (SELECT * FROM Reservas R WHERE R.Bid = 103 AND R.Sid = S.Sid)

Exemplo
Encontre nome de marinheiros que no reservaram o barco 103

SELECT S.Snome FROM Sailors S WHERE NOT EXISTS (SELECT * FROM Reservas R WHERE R.Bid = 103 AND R.Sid = S.Sid)

Exemplo
Encontre nome de marinheiros que reservaram uma nica vez o barco 103

SELECT S.Snome FROM Sailors S WHERE UNIQUE (SELECT * FROM Reservas R WHERE R.Bid = 103 AND R.Sid = S.Sid)

Condies do WHERE em consultas aninhadas

A > ANY (R: Resultado de subconsulta)

Verdadeiro se o valor do atributo A maior do que algum valor de R Verdadeiro se o valor do atributo A maior do que qualquer valor em R
Verdadeiro se o valor de A no est em R Verdadeiro se o valor de A est em R

A > ALL (R: Resultado de subconsulta)

A <> ALL (R: Resultado de subconsulta)

A = ANY (R: Resultado de subconsulta)

Exemplo

Encontre os identificadores de marinheiros cujo status melhor do que algum marinheiro chamado Horcio

SELECT S.Sid FROM Sailors S WHERE S.Status >= ANY (SELECT S2.Status FROM Sailors S2 WHERE S2.Snome = Horacio)

Exemplo

Encontre os identificadores de marinheiros que tm os maiores status.

SELECT S.Sid FROM Sailors S WHERE S.Status >= ALL (SELECT S2.Status FROM Sailors S2)

Exerccio 1

Quais so os nomes dos marinheiros mais jovens que reservaram o barco 103 ?

SELECT S.Snome FROM Sailors S, Reservas R WHERE S.Sid = R.Sid AND B.Bid = 103 AND S.Idade <= ALL (SELECT S2.Idade FROM S2 Sailors, R Reservas WHERE R.Sid = S2.Sid AND R.Bid = 103)

Consultas Aninhadas Correlacionadas (a evitar - ineficientes)


Encontre nome de marinheiros que reservaram o barco 103

SELECT S.Snome FROM Sailors S WHERE EXISTS (SELECT * Consulta executada repetidamente: uma FROM Reservas R vez para cada tupla da relao Sailors WHERE R.Bid = 103 AND R.Sid = S.Sid)

Exerccio 2

A consulta a seguir correlacionada ?

SELECT S.Snome FROM Sailors WHERE S.Idade <= ALL (SELECT S2.Idade FROM S2 Sailors, R Reservas WHERE R.Sid = S2.Sid AND R.Bid = 103) Resposta: No

Como simular operador de Interseco


Encontre os nomes de marinheiros que reservaram barcos verdes e vermelhos. SELECT S.Snome FROM Sailors S, Reservas R, Barcos B WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Vermelho AND S.Sid IN (SELECT S2.Sid FROM Sailors S2, Barcos B2, Reservas R2 WHERE S2.Sid = R2.Sid AND R2.Bid = B2.Bid AND B2.Cor = Verde)

Variante: calcula a mesma resposta ? (SIM)


SELECT S.Snome FROM Sailors S WHERE S.Sid IN ( (SELECT R.Sid FROM Barcos B, Reservas R WHERE R.Bid = B.Bid AND B.Cor = Vermelho) INTERSECT (SELECT R.Sid FROM Barcos B, Reservas R WHERE R.Bid = B.Bid AND B.Cor = Verde) )

Variante: calcula a mesma resposta ? (NO !!)


(SELECT S.Snome FROM Sailors S, Barcos B, Reservas R WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Vermelho) INTERSECT (SELECT S.Snome FROM Sailors S, Barcos B, Reservas R WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Verde)

Exerccio 3 : Operador de Diferena

D os nomes dos marinheiros que reservaram barcos vermelhos e no reservaram barcos verdes.

SELECT S.Snome FROM Sailors S, Reservas R, Barcos B WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Vermelho AND S.Sid NOT IN (SELECT S2.Sid FROM Sailors S2, Barcos B2, Reservas R2 WHERE S2.Sid = R2.Sid AND R2.Bid = B2.Bid AND B2.Cor = Verde)

Variante: Calcula a mesma resposta ? (SIM)


SELECT S.Snome FROM Sailors S WHERE S.Sid IN ( (SELECT R.Sid FROM Barcos B, Reservas R WHERE R.Bid = B.Bid AND B.Cor = Vermelho) EXCEPT (SELECT R.Sid FROM Barcos B, Reservas R WHERE R.Bid = B.Bid AND B.Cor = Verde) )

Variante: calcula a mesma resposta ? (NO !!)


(SELECT S.Snome FROM Sailors S, Barcos B, Reservas R WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Vermelho) EXCEPT (SELECT S.Snome FROM Sailors S, Barcos B, Reservas R WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Verde)

Exercicio 4 : Operador de Unio

D o nome dos marinheiros que reservaram barcos vermelhos ou verdes.

SELECT S.Snome FROM Sailors S, Reservas R, Barcos B WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Vermelho OR S.Sid IN (SELECT S2.Sid FROM Sailors S2, Barcos B2, Reservas R2 WHERE S2.Sid = R2.Sid AND R2.Bid = B2.Bid AND B2.Cor = Verde)

Variante: Calcula a mesma resposta ? (SIM)


SELECT S.Snome FROM Sailors S WHERE S.Sid IN ( (SELECT R.Sid FROM Barcos B, Reservas R WHERE R.Bid = B.Bid AND B.Cor = Vermelho) UNION (SELECT R.Sid FROM Barcos B, Reservas R WHERE R.Bid = B.Bid AND B.Cor = Verde) )

Variante: calcula a mesma resposta ? (SIM !!)


(SELECT S.Snome FROM Sailors S, Barcos B, Reservas R WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Vermelho) UNION (SELECT S.Snome FROM Sailors S, Barcos B, Reservas R WHERE S.Sid = R.Sid AND R.Bid = B.Bid AND B.Cor = Verde)

Operador de Diviso

D o nome dos marinheiros que reservaram todos os barcos.

SELECT S.SNOME FROM SAILORS S WHERE NOT EXISTS ( ( SELECT B.BID FROM BARCOS B EXCEPT (SELECT R.BID FROM RESERVAS R WHERE R.SID = S.SID) )

Identificadores de barcos que no foram reservados pelo marinheiro com identificador Sid

Variante (sem EXCEPT)

D o nome dos marinheiros que reservaram todos os barcos.

SELECT S.SNOME FROM SAILORS S WHERE NOT EXISTS (( SELECT B.BID FROM BARCOS B WHERE NOT EXISTS ( SELECT R.BID FROM RESERVAS R WHERE R.BID = B.BID AND R.SID = S.SID) )

Identificadores de barcos que no foram reservados pelo marinheiro com Identificador SID

Identificadores de barcos que foram reservados pelo marinheiro com Identificador SID

Exerccio 5

D o nome dos marinheiros que reservaram todos os barcos vermelhos.

SELECT S.SNOME FROM SAILORS S WHERE NOT EXISTS

( (SELECT B.BID FROM BARCOS B, RESERVAS R WHERE B.Cor = Vermelho) EXCEPT (SELECT R.BID FROM RESERVAS R WHERE R.SID = S.SID) )

OPERADORES DE AGREGAO

COUNT ([DISTINCT] A)

Nmero de valores da coluna A Soma dos valores da coluna A Mdia dos valores da coluna A Maior valor da coluna A Menor valor da coluna A

SUM ([DISTINCT] A)

AVG ([DISTINCT] A)

MAX(A)

MIN(A)

Exemplos: AVG, Sum

D a mdia das idades dos marinheiros SELECT AVG(S.Idade) FROM Sailors S

D a soma das idades dos marinheiros com status 10


SELECT Sum(S.Idade) FROM Sailors S WHERE S.rating = 10

Exemplos: MAX, MIN (ERRADO)

D o nome e idade do marinheiro mais velho

SELECT S.Snome, MAX(S.Idade) FROM Sailors S

Agregado no pode aparecer junto com outro atributo A MENOS QUE SE UTILIZE O OPERADOR GROUP BY

Exemplos: MAX, MIN (CORRETO)

D o nome e idade do marinheiro mais velho

SELECT S.Snome, S.Idade FROM Sailors S WHERE S.Idade = (SELECT Max(S2.Idade) FROM Sailors S2)
Resultado da consulta uma tabela com um nico elemento (um nmero) Tabela transformada em um nmero

Exemplos (NEM SEMPRE ACEITO POR ALGUNS SGBDs)

D o nome e idade do marinheiro mais velho

SELECT S.Snome, S.Idade FROM Sailors S WHERE (SELECT Max(S2.Idade) FROM Sailors S2 WHERE Sailors S2) = S.Idade

Exemplo: COUNT

Conte o nmero de marinheiros

SELECT COUNT (*) FROM Sailors

Conte os nomes diferentes de marinheiros

SELECT COUNT( DISTINCT S.Snome) FROM Sailors

Substituindo ALL por MAX

Encontre o nome dos marinheiros que so mais velhos do que o marinheiro mais velho que tem status 10.

SELECT S.Snome FROM Sailors S WHERE S.Idade >= ALL (SELECT S2.Idade FROM Sailors S2 WHERE S2.Status = 10) SELECT S.Snome FROM Sailors S WHERE S.Idade >= (SELECT MAX(S2.Idade) FROM Sailors S2 WHERE S2.Status = 10)

Substituindo ANY por MIN

Encontre o nome dos marinheiros que so mais velhos do que algum marinheiro que tem status 10.

SELECT S.Snome FROM Sailors S WHERE S.Idade >= ANY (SELECT S2.Idade FROM Sailors S2 WHERE S2.Status = 10) SELECT S.Snome FROM Sailors S WHERE S.Idade >= (SELECT MIN(S2.Idade) FROM Sailors S2 WHERE S2.Status = 10)

Exercicio 6

D a soma das idades e a mdia dos status dos marinheiros que reservaram barcos vermelhos.
SELECT Sum(S.Idade), AVG(S.Status) FROM Sailors S WHERE S.Sid IN (SELECT R.Sid FROM Reservas R, Barcos B WHERE B.Bid = R.Bid AND B.Cor = Vermelho)

GROUP BY - HAVING
SELECT <lista-atributos> FROM <lista-tabelas> WHERE <condio sobre tuplas> GROUP BY <lista-atributos-de-agrupamento> HAVING <condio sobre os grupos>

Exemplo

Para cada nvel de status, d a idade do marinheiro mais jovem neste status
Sailors Sailors
Sid Snome Status Idade 22 N1 7 45 35 7 64 N6 8 31 N3 55,5 25,5 8 32 N4 10 58 N5 35 10 71 N7 16 35 74 N6 9 29 N2 33 1 3 85 N8 25,5 95 N9 3 63,5

Resposta
Status M-Age 7 35 8 25,5

Sid 22 29 31 32 58 64 71 74 85 95

SnomeStatus Idade N1 7 45 33 N2 1 8 55,5 N3 N4 25,5 8 35 N5 10 35 N6 7 10 N7 16 N6 9 35 N8 3 25,5 3 N9 63,5

10
9 1 3

16
35 33 25,5

SELECT S.Status, MIN(S.Idade) AS M-Age FROM Sailors S GROUP BY S.Status

Exemplo

Para cada nvel de status, d a idade do marinheiro mais jovem neste status, excluindo-se o status 1

SELECT S.Status, Min(S.Idade) AS M-Age FROM Sailors S GROUP BY S.Status HAVING S.Status <> 1

Exemplo

Para cada nvel de status diferente de 1, d a idade do marinheiro mais jovem neste status que reservou o barco 102.

SELECT S.Status, Min(S.Idade) FROM Sailors S WHERE S.Sid in (Select R.Sid FROM Reservas R WHERE R.Bid = 102 ) GROUP BY S.Status HAVING S.Status <> 1

Exemplo

Encontre a idade do marinheiro mais jovem mas que possa votar (com pelo menos 18 anos) para cada nivel de status com ao menos dois marinheiros neste nvel.
Sailors Resposta Status 7
M-Age Sid Snome Status Idade 22 N1 7 45 35 7 64 N6 8 31 N3 55,5 25,5 8 32 N4 58 N5 10 35 71 N7 10 16 9 35 74 N6 29 N2 33 1 25,5 3 85 N8 95 N9 3 63,5

SELECT S.Status, Min(S.Idade) AS M-Age FROM Sailors S WHERE S.Idade >= 18 GROUP BY S.Status HAVING COUNT(*) > 1

35

8
3

25,5
25,5

Exemplo

Encontre a idade do marinheiro mais jovem mas que possa votar (com pelo menos 18 anos) para cada nivel de status com ao menos dois marinheiros neste nvel. Exiba a resposta ordenada por Status.
Resposta

SELECT S.Status, Min(S.Idade) AS M-Age FROM Sailors S WHERE S.Idade >= 18 GROUP BY S.Status HAVING COUNT(*) > 1 ORDER BY S.Status

Status M-Age
3 7 8 25,5 35 25,5

Exemplo

Encontre a idade do marinheiro mais jovem mas que possa votar (com pelo menos 18 anos) para cada nivel de status com ao menos dois marinheiros neste nvel e onde todo marinheiro neste nvel tenha no mximo 60 anos.
Sailors Resposta Status Min-A 35 7 8 25,5
Sid Snome Status Idade 22 N1 7 45 7 64 N6 35 8 55,5 31 N3 32 N4 25,5 8 58 N5 10 35 71 N7 10 16 9 74 N6 35 29 N2 1 33 3 25,5 85 N8 63,5 3 95 N9 97 N10 24 3

SELECT S.Status, Min(S.Idade) AS Min-A FROM Sailors S WHERE S.Idade >= 18 GROUP BY S.Status HAVING COUNT(*) > 1 AND EVERY (S.Idade <= 60)

A consulta a seguir equivalente precedente ?

SELECT S.Status, Min(S.Idade) FROM Sailors S WHERE S.Idade >= 18 AND S.Idade <= 60 GROUP BY S.Status HAVING COUNT(*) > 1

Resposta : No so equivalentes !
SELECT S.Status, Min(S.Idade) AS Min-AGE FROM Sailors S WHERE S.Idade >= 18 AND S.Idade <= 60
Sailors
Sid Snome Status Idade 22 N1 7 45 7 64 N6 35 8 55,5 31 N3 32 N4 25,5 8 58 N5 10 35 16 71 N7 10 9 74 N6 35 1 33 29 N2 3 25,5 85 N8 95 N9 3 63,5 97 N10 3 24

Resposta

Status Min-A 35 7
8 3 25,5 24

GROUP BY S.Status HAVING COUNT(*) > 1

Encontre a idade e status dos marinheiros mais jovens que possa votar (com pelo menos 18 anos) e que tenha no mximo 60 anos, agrupados por status, onde cada grupo tem ao menos dois marinheiros nestas condies

Exemplo

Encontre a idade do marinheiro mais jovem mas que possa votar (com pelo menos 18 anos) para cada nivel de status com ao menos dois marinheiros neste nvel e onde pelo menos um marinheiro no nvel tenha idade inferior a 60 anos.

SELECT S.Status, Min(S.Idade) FROM Sailors S WHERE S.Idade >= 18 GROUP BY S.Status HAVING COUNT(*) > 1 AND ANY (S.Idade <= 60)

Exerccio 7

Para cada barco vermelho, d o nmero de reservas que foram feitas para este barco.

SELECT COUNT(*) AS ContadorReserva FROM Barcos B, Reservas R WHERE R.Bid = R. Bid and B.Cor = Verm GROUP BY B.Bid

Exercicio 8

Encontre a mdia de idade dos marinheiros com mais de 18 anos, para cada nvel de status que tem ao menos dois marinheiros.

SELECT S.Status, AVG(S.Idade) AS Min-AGE FROM Sailors S WHERE S.Idade > 18 GROUP BY S.Status HAVING COUNT(*) > 1

Exerccio 9 (para casa)

D os status para os quais a mdia de idades dos marinheiros neste status igual menor das mdias de idades de cada status.

SELECT Temp.Status FROM (SELECT S.Status, AVG(S.Idade) FROM Sailors S GROUP BY S.Status) AS Temp WHERE Temp.AVG = (SELECT MIN (Temp.AVG) FROM Temp)

Resumo Geral do uso de Agregados


SELECT <lista-seleo> FROM <lista-tabelas> WHERE <condio-sobre-tuplas> GROUP BY <lista-atributos-de-agrupamento> HAVING <condio-sobre-os-grupos> 1. lista-seleo = lista de atributos + lista de termos do tipo operador(atributo) AS novo-atributo 2. Todo atributo que aparece em lista de atributos deve aparecer na lista-atributos-de-agrupamento. 3. Atributos que aparecem em condio-sobre-os-grupos devem aparecer em operador(atributo) ou em lista-atributos-deagrupamento.

Exemplo
SELECT S.Status ,Min( S.Idade) AS Min-Age FROM Sailors S WHERE S.Idade >= 18 GROUP BY S.Status HAVING S.Status > 5 AND EVERY ( S.Idade <= 60)

Particularidade de SQL 1999


Se a lista-atributos-de-agrupamento contm a chave primria de uma tabela da lista-tabelas ento cada coluna desta tabela s tem um nico valor em cada grupo. Em SQL1999, tais colunas podem aparecer na lista de atributos da lista-seleo.

SELECT S.Status, S.Snome, AVG(S.Idade) AS Min-AGE FROM Sailors S Chave de Sailors GROUP BY S.Sid Logo: os grupos tm um nico elemento HAVING COUNT(*) > 1

You might also like