Este documento describe diferentes consultas SQL para recuperar datos de una base de datos relacional. Explica cómo usar operadores como UNION, INTERSECT y EXCEPT para combinar resultados de consultas. También cubre el uso de subconsultas, JOIN, GROUP BY, HAVING, ordenamiento y agregaciones para extraer y resumir información de las tablas de una base de datos.
2. Encontrar los sid’s de los marineros que han reservado un bote
rojo o verde
• UNION: Se puede usar para obtener la union de dos
sets de tuplas compatibles-en-union (que son ellos
mismos resultados de SQL queries).
SELECT R.sid
FROM Botes B,Reservacion R
WHERE R.bid=B.bid AND
(B.color=‘rojo’OR B.color=‘verde’)
SELECT R.sid
FROM Botes B, Reservacion R
WHERE R.bid=B.bid AND B.color=‘rojo’
UNION
SELECT R.sid
FROM Botes B, Reservacion R
WHERE R.bid=B.bid AND B.color=‘verde’
Vs.
3. SELECT R.sid
FROM Boats B,Reserves R
WHERE R.bid=B.bid AND
(B.color=‘red’ AND B.color=‘green’)
Encontrar los sids de los marineros que han reservado un bote
rojo y un bote verde
• Si simplemente reemplazamos OR por AND en el query
anterior, obtenemos la respuesta incorrecta. (Por que?)
• Podemos utilizar un self-join:
SELECT R1.sid
FROM Botes B1, Reservacion R1,
Botes B2, Reservacion R2
WHERE R1.sid=R2.sid
AND R1.bid=B1.bid
AND R2.bid=B2.bid
AND (B1.color=‘rojo’ AND B2.color=‘verde’)
4. AND Continua…
• INTERSECCION: Se puede utilizar
para obtener la intersección
de dos sets de tuplas
compatibles_en_union.
• También: EXCEPT (a veces
llamado MINUS) ( — )
• Incluido en el estándar
SQL/92, pero muchos sistemas
no los incluyen.
SELECT S.sid
FROM Marineros S, Botes B,
Reservacion R
WHERE S.sid=R.sid
AND R.bid=B.bid
AND B.color=‘rojo’
INTERSECT
SELECT S.sid
FROM Marineros S, Botes B,
Reservacion R
WHERE S.sid=R.sid
AND R.bid=B.bid
AND B.color=‘verde’
Key field!
5. Encuentre los sid’s de los marineros que han reservado un bote
rojo pero no han reservadoun bote verde
SELECT S.sid
FROM Marineros S, Botes B,
Reservacion R
WHERE S.sid=R.sid
AND R.bid=B.bid
AND B.color=‘rojo’
EXCEPT
SELECT S.sid
FROM Marineros S, Botes B,
Reservacion R
WHERE S.sid=R.sid
AND R.bid=B.bid
AND B.color=‘verde’
6. • Herramienta poderosa en SQL: WHERE puede
contener un SQL query!
– También FROM y HAVING.
• Para encontrar los marineros que no han reservado
el #103, usar NOT IN.
SubQueries
SELECT S.snombre
FROM Marineros S
WHERE S.sid IN (SELECT R.sid
FROM Reservacion R
WHERE R.bid=103)
Nombres de los marineros que han reservado el bote #103:
7. SubQueries con Correlacion
• EXISTS es otro operador de comparación, como IN.
• También se puede especificar NOT EXISTS
• Si UNIQUE se usa, y * es reemplazado por R.bid, encuentra los
marineros con al menos una reservación para el bote #103.
– UNIQUE elimina tuplas duplicadas en un subquery;
– Pensar que el subquery es una llamada a función que corre un
query!
SELECT S.snombre
FROM Marineros S
WHERE EXISTS (SELECT *
FROM Reservacion R
WHERE R.bid=103 AND S.sid=R.sid)
Encontrar los nombres de los marineros que han reservado el
bote #103:
8. Más en Operadores de Comparación
• Hemos visto IN, EXISTS y UNIQUE. También se pueden
usar NOT IN, NOT EXISTS y NOT UNIQUE.
• Tambien disponibles: ANY, SOME, ALL
• Encuentre los marineros cuyo rating es mayor que
el de otro marinero llamado Horatio:
SELECT *
FROM Marineros S
WHERE S.rating > ANY (SELECT S2.rating
FROM Marineros S2
WHERE S2.snombre=‘Horatio’)
9. Reescribiendo Queries con INTERSECT Usando IN
• Similarmente, queries con EXCEPT se reescriben
usando NOT IN.
Encontrar sid’s de marineros que han reservado un bote verde y un bote rojo:
SELECT R.sid
FROM Botes B, Reservacion R
WHERE R.bid=B.bid
AND B.color=‘rojo’
AND R.sid IN (SELECT R2.sid
FROM Botes B2, Reservacion R2
WHERE R2.bid=B2.bid
AND B2.color=‘verde’)
10. División en SQL
SELECT S.snombre
FROM Marineros S
WHERE NOT EXISTS (SELECT B.bid
FROM Botes B
WHERE NOT EXISTS (SELECT R.bid
FROM Reservacion R
WHERE R.bid=B.bid
AND R.sid=S.sid))
Marineros S que...
No hay bote B...
Que no hayan reservado R
Encontrar marineros que han reservado todos los botes.
11. Operadores de Agregación
COUNT (*)
COUNT ( [DISTINCT] A)
SUM ( [DISTINCT] A)
AVG ( [DISTINCT] A)
MAX (A)
MIN (A)
SELECT AVG (S.edad)
FROM Marineros S
WHERE S.rating=10
SELECT COUNT (*)
FROM Marineros S
Una sola columna
SELECT COUNT (DISTINCT S.rating)
FROM Marineros S
WHERE S.snombre=‘Bob’
•El resultado es un solo número(relación con
una sola fila y una sola columna)
•Operadores de agregación no se pueden
utilizar en la clausula WHERE
12. Encontrar el nombre y edad del marinero(s) más
viejo
• El primer query es
incorrecto!
• El segundo query es
equivalente al tercero
– Permitido en SQL/92
standard, pero no en
algunos sistemas.
SELECT S.snombre, MAX (S.edad)
FROM Marineros S
SELECT S.snombre, S.edad
FROM Marineros S
WHERE S.edad =
(SELECT MAX (S2.edad)
FROM Marineros S2)
SELECT S.snombre, S.edad
FROM Marineros S
WHERE (SELECT MAX (S2.edad)
FROM Marineros S2)
= S.edad
13. GROUP BY y HAVING
• Hasta ahora, hemos aplicado operadores de agregación
a todas las tuplas (que clasifican).
– A veces, queremos aplicarlas a cada una de muchos grupos
de tuplas.
• Considere: Encontrar la edad del marinero más joven
para cada nivel de rating.
– En general, no sabemos cuantos niveles de rating existen, y
cuales son los valores de rating para estos niveles!
– Supongamos que los valores de rating van de 1 a10;
Podemos escribir 10 queries como estos(!):
SELECT MIN (S.age)
FROM Sailors S
WHERE S.rating = i
For i = 1, 2, ... , 10:
14. Queries Con GROUP BY
La lista-objetivos contiene (i) lista de nombres de columnas y
(ii) términos con operadores de agregación(ej., MIN (S.edad)).
– lista de nombres de columnas(i) pueden contener solo atributos
de la lista-de-agrupamiento.
SELECT [DISTINCT] lista-objetivos
FROM lista-de-relaciones
[WHERE clasificaciones]
GROUP BY lista-de-agrupamiento
• Para generar valores para una columna basado en grupos de
filas, se usan funciones de agregación en el SELECT con la clausula
GROUP BY
16. Ejemplos Group By
SELECT S.rating, AVG (S.edad)
FROM Marineros S
GROUP BY S.rating
Para cada rating, encuentre la edad promedio
de los marineros
Para cada rating encuentre la edad del marinero
más joven con edad 18
SELECT S.rating, MIN (S.edad)
FROM Marineros S
WHERE S.edad>= 18
GROUP BY S.rating
17. Evaluación Conceptual de Group By
• El producto cruz de lista-de-relaciones es
procesado, tuplas que fallan la clasificación son
ignoradas, campos `innecesarios’ fields son
borrados, y las tuplas que quedan son divididas en
grupos por el valor de atributos en lista-de-
agrupamiento.
• Una tupla de respuesta es generada por cada
grupo.
18. SELECT S.rating, MIN (S.edad)
FROM Marineros S
WHERE S.edad>= 18
GROUP BY S.rating
sid snombre rating edad
22 dustin 7 45.0
31 lubber 8 55.5
71 zorba 10 16.0
64 horatio 7 35.0
29 brutus 1 33.0
58 rusty 10 35.0
1. Producto cruz
rating edad
1 33.0
7 45.0
7 35.0
8 55.5
10 35.0
2. Se borran columnas no necesarias, filas
forman grupos
3. Se lleva a cabo
la agregación
rating age
1 33.0
7 35.0
8 55.0
10 35.0
Tabla de Respuesta
19. Encuentre el número de
reservaciones para cada bote rojo.
• Agrupando a través de un join de dos
relaciones.
SELECT B.bid, COUNT(*)AS numres
FROM Botes B, Reservacion R
WHERE R.bid=B.bid
AND B.color=‘rojo’
GROUP BY B.bid
20. SELECT B.bid, COUNT (*) AS scount
FROM Botes B, Reservacion R
WHERE R.bid=B.bid AND B.color=‘rojo’
GROUP BY B.bid
1
b.bid b.color r.bid
101 azul 101
102 rojo 101
103 verde 101
104 rojo 101
101 azul 102
102 rojo 102
103 verde 102
104 rojo 102
b.bid b.color r.bid
102 rojo 102
2
b.bid scount
102 1
answer
21. Queries con GROUP BY y HAVING
• Se usa la clausula HAVING con la de GROUP BY
para restringir qué grupos de filas son devueltas en
el set de resultados
SELECT [DISTINCT] lista-objetivos
FROM lista-de-relaciones
[WHERE clasificaciones]
GROUP BY lista-de-agrupamiento
HAVING clasificación-de-grupos
22. Evaluación Conceptual
• Se forman grupos como antes.
• La clasificación-de-grupos es aplicada para eliminar
algunos grupos.
– Las expresiones en la clasificación-de-grupos debe
tener un solo valor por grupo!
– Significa que, atributos en clasificación-de-grupos
deben ser argumentos de un operador de agregación o
también deben aparecer en la lista-de-agrupamiento.
• Una tupla de respuesta es generada por cada clasificación
de grupo.
23. Encuentre el rating del marinero más joven
con edad 18, para cada rating con al menos 2 de esos
marineros
SELECT S.rating, MIN (S.edad)
FROM marineros S
WHERE S.edad >= 18
GROUP BY S.rating
HAVING COUNT (*) > 1
rating
7 35.0
Resultado
rating edad
1 33.0
7 45.0
7 35.0
8 55.5
10 35.0
2
rating m-edad count
1 33.0 1
7 35.0 2
8 55.0 1
10 35.0 1
3
sid snombre rating edad
22 Dustin 7 45.0
31 lubber 8 55.5
71 zorba 10 16.0
64 horatio 7 35.0
29 brutus 1 33.0
58 rusty 10 35.0
24. División en SQL
SELECT S.snombre
FROM Marineros S
WHERE NOT EXISTS (SELECT B.bid
FROM Botes B
WHERE NOT EXISTS (SELECT R.bid
FROM Reservacion R
WHERE R.bid=B.bid
AND R.sid=S.sid))
Marineros S que...
No hay bote B...
Que no hayan reservado R
Encontrar marineros que han reservado todos los botes.
25. SELECT snombre FROM Marineros
WHERE Sid NOT IN (
SELECT s.Sid
FROM Marineros s, Botes b
WHERE (s.Sid, b.Bid) NOT IN (
SELECT Sid, Bid FROM Reservacion));
Encontrar marineros que han reservado todos los botes.
26. • Se puede hacer esto con
Group By y Having?
SELECT S.snombre
FROM Marineros S, reservacion R
WHERE S.sid = R.sid
GROUP BY S.snombre, S.sid
HAVING
COUNT(DISTINCT R.bid) =
( Select COUNT (*) FROM Botes)
Encontrar marineros que han reservado todos los botes.
27. SELECT S.snombre
FROM Marineros S, reservacion R
WHERE S.sid = R.sid
GROUP BY S.snombre, S.sid
HAVING
COUNT(DISTINCT R.bid) =
( Select COUNT (*) FROM Botes)
s.snombre s.sid r.sid r.bid
Dustin 22 22 101
Lubber 31 22 101
Bob 95 22 101
Dustin 22 95 102
Lubber 31 95 102
Bob 95 95 102
s.name s.sid bcount
Dustin 22 1
Bob 95 1
bid bnombre color
101 Interlake azul
102 Interlake rojo
103 Clipper verde
104 Marine rojo
Count (*) from boats = 4
Se aplica la clausula having a los grupos
s.name s.sid
28. Ordenando los resultados de un Query
• ORDER BY columna [ ASC | DESC] [, ...]
• Se puede ordenar por cualquier columna
en la lista de SELECT, incluyendo
expresiones o agregaciones:
SELECT S.rating, S.snombre, S.edad
FROM Marineros S, Botes B, Reservacion R
WHERE S.sid=R.sid
AND R.bid=B.bid AND B.color=‘rojo’
ORDER BY S.rating, S.snombre;
SELECT S.sid, COUNT (*) AS redrescnt
FROM Marineros S, Botes B, Reservacion R
WHERE S.sid=R.sid
AND R.bid=B.bid AND B.color=‘rojo’
GROUP BY S.sid
ORDER BY redrescnt DESC;
29. Queries de SQL Básicos - Resumen
• Una ventaja del modelo relacional es su bien-definida
semántica de query.
• SQL provee funcionalidad parecida a la del modelo básico
relacional.
– Hay algunas diferencias en manejo de
duplicados, valores null, operadores, etc.
• Usualmente, hay muchas maneras de escribir un query
– El sistema es responsable de encontrar una forma
rápida de ejecutar un query no importa cómo esté
escrito.
• Hay más funcionalidades más allá de estas características
básicas. Las cuales veremos en clases siguientes.