523,3k - Mestre a casa

Anuncio
SQL Avanzado
José Muñoz Jimeno
Febrero 2015
Control de cambios
Versión
Fecha
Comentarios
1.0
13/02/2015 Primera versión para el curso “Introducción a las bases de
datos con MySQL” en el COITCV
La última versión de este documento puede descargarse en
http://mestreacasa.gva.es/web/munoz_jos24/cursos
Índice
Combinaciónes de tablas
Producto cartesiano
Combinación o reunión
Combinación externa
Subconsultas
En el FROM
En WHERE o HAVING
En SELECT
Consultas de unión
Sentencias SELECT avanzadas
Combinaciones de tablas

Consultas que toman datos de más de una tabla
Subconsultas

Tendremos una consulta SQL dentro de otra
Consultas de unión

Uniremos más de una sentencia SQL
Combinaciones de tablas.
Hasta ahora FROM <tabla> → ahora FROM <tabla s>
Hay varias formas de usar más de una tabla:
Producto cartesiano → no útil. Conocer, para evitarla
 Combinación o reunión → la más utilizada
 Combinación externa → variante de la anterior. Muy útil.

Combinaciones de tablas
Producto cartesiano
SELECT …
FROM tablaA, tablaB
Producto cartesiano o cross join
Cada registro de una relación se combina con TODOS los de
la otra
Cualificar: ahora hemos de
#filas_resultado = #filasA x #filas B
decir de qué tabla es cada
Ejemplo:
campo si hay campos
SELECT Empleat.Nom, Familiar.Nom iguales
FROM Empleat, Familiar;
Resultado: 70 filas: 7 Empleat x 10 Familiar
No proporciona ninguna información útil
Combinaciones de tablas
Producto cartesiano
SELECT Empleat.Nom,
Familiar.Nom
FROM Empleat,Familiar;

Resultado:
70 filas: 7 Empleat x 10
Familiar
 No proporciona ninguna
información útil
 Ojo: la BD lo hace en otras
combinaciones antes de
quedarse con las filas que
le interesan → ver orden
magnitud consultas

Combinaciones de tablas
Combinación interna
SELECT ...
FROM tabla1 INNER JOIN tabla2 ON tabla1.campo1 =
tabla2.campo2
Combinación interna o combinación o reunión
Nos interesa combinar tablas que coincidan en un campo de
cada una
Generalmente una clave externa y la principal a la que apunta
 Ej: Combinar cada empleado con los familiares que tiene
SELECT Empleat.Nom, Familiar.Nom
FROM Empleat INNER JOIN Familiar ON Empleat.Dni
= Familiar.Dni;

Combinaciones de tablas
Combinación interna
Sintaxis alternativa:
SELECT ...
FROM tabla1, tabla2
WHERE tabla1.campo1 = tabla2.campo2;
Es como hacer un producto cartesiano y luego quedarnos
con las filas que nos interesan
Es más utilizada esta sintaxis, pero es cuestión de gustos
Ejemplo
SELECT Empleat.Nom, Familiar.Nom
FROM Empleat, Familiar
WHERE Empleat.Dni = Familiar.Dni;
Combinaciones de tablas
Combinación interna - Ejemplos
Sacar el nombre de los departamentos y sus empleados
SELECT nom_d,nom
FROM Departament INNER JOIN Empleat ON
Departament.num_d=Empleat.departament;
Sacar de cada departamento su nombre y el de su director
SELECT nom_d, nom
FROM Departament INNER JOIN Empleat ON
Departament.director=Empleat.dni;
Sacar el nombre de los departamentos y el número de empleados
de cada uno
SELECT nom_d, COUNT(dni) AS 'Num_emp'
FROM Departament INNER JOIN Empleat ON
Departament.num_d=Empleat.departament
GROUP BY nom_d;
Combinaciones de tablas
Combinación interna - 3 ó más tablas
Ej: Nombre de un departamento, de sus empleados y el
nombre de sus familiares.
SELECT nom_d, Empleat.nom, Familiar.nom AS Nom_fam
FROM (Departament INNER JOIN Empleat ON
Departament.num_d=Empleat.departament)
INNER JOIN Familiar ON Empleat.dni=Familiar.dni;
o bien
SELECT nom_d, Empleat.nom, Familiar.nom
FROM Departament , Empleat , Familiar
WHERE Departament.num_d=Empleat.departament AND
Empleat.dni=FAMILIAR.dni;
En general n tablas → n-1 condiciones de combinación
Combinaciones de tablas
Combinación interna - 3 ó más tablas - Ejemplo
Obtener nombre de los empleados con el nombre de los
proyectos en los que trabajan.
Necesitamos: Empleat.nom y Projecte.nom_p
 ¡Pero Empleat y Projecte no se pueden combinar!
 Necesitamos Treballa, aunque no mostremos nada de ella
SELECT Empleat.nom, Projecte.nom_p
FROM (Empleat INNER JOIN Treballa ON
Empleat.dni=Treballa.dni) INNER JOIN Projecte ON
Treballa.num_p=Projecte.num_p;
o bien
SELECT Empleat.nom, Projecte.nom_p
FROM Empleat, Treballa, Projecte
WHERE Empleat.dni=Treballa.dni AND
Treballa.num_p=Projecte.num_p;

Combinaciones de tablas
Combinación interna - Una tabla más de una vez
Ej: Queremos obtener el nombre de los empleados y su
supervisor
¡Está en la misma tabla! ¿Cómo la ponemos 2 veces?
 Renombrándolas: FROM tabla [AS] T1
SELECT E1.nom AS 'Empleado' , E2.nom as Supervisor
FROM Empleat E1 INNER JOIN Empleat E2 ON
E1.supervisor=E2.dni;
O bien
SELECT E1.nom AS 'Empleado' , E2.nom as Supervisor
FROM Empleat E1, Empleat E2
WHERE E1.supervisor=E2.dni;

Combinaciones de tablas
Combinación interna - Clave externa formada por
más de un campo
Hemos de combinar por todos los campos
Ej: Cuenta corriente depende en identificación de Sucursal
Clave ppal de Sucursal 2 campos: n_ent, n_suc
 Clave externa de CC: los dos campos

SELECT C.n_ent , C.n_suc , n_cc , S.nom , C.saldo
FROM SUCURSAL S INNER JOIN COMPTE_CORRENT
C ON S.n_ent=C.n_ent AND S.n_suc=C.n_suc;

SELECT C.n_ent , C.n_suc , n_cc , S.nom , C.saldo
FROM SUCURSAL S, COMPTE_CORRENT C
WHERE S.n_ent=C.n_ent AND S.n_suc=C.n_suc

Nota: se ha usado S y C para acortar
Combinaciones de tablas
Combinación externa
SELECT ...
FROM tabla1 LEFT JOIN tabla2 ON tabla1.campo1 =
tabla2.campo2
Obtendremos todas las entradas de la tabla 1 y aquellas que
estén relacionadas de la tabla2
Si cambiamos LEFT por RIGHT obtendremos todas las de
tabla2 y las relacionadas de tabla1
Ejemplo
SELECT Empleat.nom, Familiar.nom AS Nom_fam
FROM Empleat LEFT JOIN Familiar ON
Empleat.dni=Familiar.dni
Combinaciones de tablas
Combinación externa - Ejemplos
Obtener el nombre de los empleados con el número de
familiares que tiene cada uno → contar clave ppal Familiar
SELECT Empleat.nom, COUNT(Familiar.dni)
FROM Empleat LEFT JOIN Familiar ON
Empleat.dni=Familiar.dni
GROUP BY Empleat.nom;
Obtener los nombres de los Departamentos i los nombres de
los Proyectos coordinados por cada uno, incluyendo
Departamentos que no coordinan ningún proyecto
SELECT nom_d,nom_p
FROM Departament LEFT JOIN Projecte ON
Departament.num_d=Projecte.departament;
Combinaciones de tablas
Combinación externa - Ejemplos
Obtener el nombre de todos los empleados y el número de
empleados a los que supervisan
SELECT E1.nom, COUNT(E2.dni) AS 'Num supervisados'
FROM Empleat E1 LEFT JOIN Empleat E2 ON
E1.dni=E2.supervisor
GROUP BY E1.nom;
Obtener los empleados sin familiares
SELECT Empleat.nom
FROM Empleat LEFT JOIN Familiar ON
Empleat.dni=Familiar.dni
WHERE Familiar.dni IS NULL;
Combinaciones de tablas
Combinación externa - Ejemplos
Obtener el nombre de todos los departamentos, el de sus
empleados y el de sus familiares.
SELECT nom_d, Empleat.nom, Familiar.nom
FROM (Departament LEFT JOIN Empleat ON
Departament.num_d=Empleat.departament)
LEFT JOIN Familiar ON Empleat.dni=Familiar.dni
ORDER BY 1,2,3;
Subconsultas
Una consulta dentro de otra consulta
Puede ir en:
FROM
 Será el origen de datos. Dará los datos a la consulta
principal.
 WHERE o HAVING
 Formará parte de una condición. Podremos comparar, en
la consulta principal, un campo con lo que devuelva la
subconsulta
 Tendremos operadores y predicados especiales
 SELECT
 Para obtener un resultado global que no afectará al resto
de la consulta principal

Subconsultas
En el FROM
SELECT ...
FROM ( Subconsulta )
Ej: Queremos obtener la media de empleados por
departamento. Obtenemos número de empleados por
departamento y después obtenemos la media
SELECT avg( Cuantos )
FROM (
SELECT COUNT( * ) AS Cuantos
FROM Empleat
GROUP BY Departament) AS C;



Se ejecuta de dentro a fuera → crear primero subconsulta
Necesario alias en campo de la subconsulta para referenciarla
Hemos de dar un nombre a la subconsulta para que funcione
Subconsultas
En el WHERE o HAVING
SELECT ...
FROM Tabla
WHERE campo operador ( Subconsulta )
Comparamos un campo de la tabla con el resultado de una
subconsulta → puede usar la misma tabla u otras
Ej: Obtener empleados que cobran más que la media
SELECT *
FROM Empleat
WHERE sou > (SELECT AVG(sou)
FROM Empleat);
En estas no hace falta dar
nombre a la subconsulta
Subconsulta devuelve 1 valor. Comparamos sou con ese valor
Subconsultas
En el WHERE o HAVING
Operadores que pueden usarse:
De comparación → =, <, >, >=, <=, <>, ALL, ANY, SOME
Operador IN
Operador EXISTS
Subconsultas
En el WHERE o HAVING - Operadores comparación
De comparación
=, <, >, >=, <=, <> → Si subconsulta devuelve 1 sólo valor
ALL, ANY, SOME → Subconsulta devuelve varios valores
ANY y SOME→cualquiera (sinónimos) ALL→ Todos
SELECT *
FROM Empleat
WHERE sou = (SELECT MAX(sou)
FROM Empleat
GROUP BY departament);
¿Funcionará?
No, ¿con qué compara
el sou de cada empleat?
SELECT *
FROM Empleat
WHERE sou = ANY (SELECT MAX(sou)
FROM Empleat
GROUP BY departament);
Funcionará para
cualquier sou que sea
igual que alguno de los
más altos de cada
departamento
Subconsultas
En el WHERE o HAVING - Operador IN
La comparación será cierta si el valor del campo está entre
los devueltos por la subconsulta
También podemos usar NOT IN
Ej: Empleados que no tienen familiares
SELECT *
FROM Empleat
WHERE dni NOT IN (
SELECT dni
FROM Familiar);
Subconsultas
En el WHERE o HAVING - Operador EXISTS
El más “incómodo”
No se compara un campo con el resultado de la subconsulta
Se pone [NOT] EXISTS subconsulta
Condición será cierta si subconsulta devuelve alguna fila
Ejemplo anterior: empleados sin familiares
Hemos de conseguir que subconsulta no devuelva filas para los
empleados sin familiares
De palabra: empleados para los que no existe ningún registro
en Familiar con su dni
En subconsulta
SELECT *
hacemos referencia a
FROM Empleat
campo de la principal
WHERE NOT EXISTS (SELECT *
Se va ejecutando la
subconsulta para
FROM Familiar
cada fila de la
WHERE dni= Empleat.dni);
principal
●
●
Subconsulta
En el SELECT
SELECT ... ( Subconsulta )
FROM Tabla
La subconsulta se usa para obtener UN valor a usar en el
select
Ej: Obtener la diferencia del sueldo de cada empleado con la
media
SELECT nom, sou, sou-(SELECT AVG(sou) FROM Empleat)
FROM Empleat;
Subconsultas
Ejemplos
Obtener el número de horas máximo y mínimo destinadas a
un proyecto
SELECT MAX(cuantas),MIN(cuantas)
FROM (SELECT SUM(hores) AS cuantas
FROM Treballa
GROUP BY num_p) AS T;
Obtener empleados sin descendientes (fill o filla)
SELECT *
FROM Empleat
WHERE dni NOT IN (SELECT DISTINCT dni
FROM Familiar
WHERE parentesc LIKE 'fill%');
Subconsultas
Ejemplos
Obtener toda la información de los empleados que cobran
más y menos en la empresa
SELECT * FROM Empleat
WHERE sou = (SELECT MAX(sou)
FROM Empleat)
OR sou = (SELECT MIN(sou)
FROM Empleat);
Obtener los empleados con un sueldo mayor que la media
de su departamento
La subconsulta se
ejecuta una vez para
cada registro de la
consulta principal
SELECT nom, departament, sou
FROM Empleat E1
WHERE sou > (SELECT Avg(sou)
FROM Empleat
WHERE departament= E1.departament);
Subconsultas
Ejemplos
Obtener dni y nombre de los empleados para los cuales la
media de horas trabajadas en proyectos, es superior a la
media general de horas trabajadas en proyectos.
SELECT Empleat.dni, nom, AVG(hores) AS TotalHores
FROM Empleat,Treballa
WHERE Empleat.dni = Treballa.dni
GROUP BY Empleat.dni, nom
HAVING AVG(hores) > (SELECT AVG(hores)
FROM Treballa);
Subconsultas
Ejemplos
Obtener el nombre de departamento, el número de
empleados y el % que supone respecto al total de
empleados.
SELECT nom_d, COUNT(dni), COUNT(dni)*100/(SELECT
COUNT(*) FROM Empleat)
FROM Departament, Empleat
WHERE num_d=departament
GROUP BY nom_d;
Consultas de unión
[TABLE] consulta1
UNION [ALL]
[TABLE] consulta2 …
Mostrará las filas de una consulta a continuación de la otra
Si queremos usar una tabla ponemos TABLE nombre_tabla
Ambas consultas deben devolver
Mismo número de campos
De tipos compatibles
Si hay una fila repetida en una o más consultas la mostrará 1
sola vez → si las queremos todas poner ALL
Nombres de los campos los da primera consulta
Si queremos ordenar, después de la última consulta
Consultas de unión
Ejemplo
Obtener fecha nacimiento y nombre de empleados y
familiares
SELECT Nom, Data_n
FROM Empleat
UNION
SELECT Nom, Data_n
FROM Familiar
ORDER BY data_n;
Descargar