GBD UD4 Manipulación Datos SQL.
GBD UD4 Manipulación Datos SQL.
distrinct
U.D. 4 Manipulación de datos en SQL e.department_id 1º ASIR-GBD. 2022-2023
from employees e;
U.D. 4 Manipulación de datos en SQL
Índice de contenido
1 Introducción..................................................................................................................3
2 Características del lenguaje SQL.................................................................................3
2.1 Componentes de un entorno de ejecución...........................................................4
2.2 Posibles agentes SQL. Posibles modos de ejecución SQL..................................5
3 Sublenguajes de SQL..................................................................................................5
3.1 Reglas sintácticas en SQL....................................................................................6
4 Elementos básicos de SQL..........................................................................................7
4.1 Tipos de datos...................................................................................................... 7
4.1.1 Tipos BUILT-IN de Oracle.............................................................................9
4.1.2 Tipos definidos por el usuario......................................................................12
4.2 Constantes..........................................................................................................12
4.3 Operadores básicos............................................................................................14
4.3.1 Operadores aritméticos...............................................................................14
4.3.2 Operadores relacionales............................................................................. 14
4.3.3 Operadores lógicos..................................................................................... 14
4.3.4 Operador Concatenación ||..........................................................................15
4.3.5 Prioridad y asociatividad de operadores.....................................................16
5 LENGUAJE DE MANIPULACIÓN DE DATOS (DML). SELECT................................17
5.1 Consultas simples con SELECT.........................................................................17
5.1.1 Introducción.................................................................................................17
5.1.2 Sintaxis de la sentencia SELECT:...............................................................17
5.1.3 Operadores BETWEEN, IS NULL, IN y LIKE..............................................21
Actividades propuestas 1.................................................................................25
5.2 Consultas sobre varias tablas. Cláusula JOIN....................................................26
5.2.1 JOIN. SINTAXIS SQL92..............................................................................27
5.2.2 JOIN. SINTAXIS SQL99..............................................................................29
5.2.3 Relaciones sin igualdad. No equijoins.........................................................33
Actividades propuestas 2.................................................................................34
5.3 Funciones de grupos de valores.........................................................................35
5.4 Agrupación de elementos. GROUP BY y HAVING.............................................36
Actividades propuestas 3.................................................................................39
5.5 Subconsultas...................................................................................................... 40
5.5.1 Subconsultas monofila................................................................................ 40
5.5.2 Subconsultas multifila..................................................................................41
5.5.3 Subconsultas multicolumna.........................................................................41
5.5.4 Subconsulta correlacionada........................................................................42
5.5.5 Operador EXISTS........................................................................................42
5.6 Operadores de conjunto.....................................................................................43
Actividades propuestas 4.................................................................................44
6 Funciones...................................................................................................................45
6.1 Funciones numéricas..........................................................................................45
6.2 Funciones de cadena......................................................................................... 47
6.3 Funciones de fechas...........................................................................................48
6.4 Funciones de conversión....................................................................................49
6.5 Otras funciones y variables de retorno...............................................................56
7 DML (continuación)....................................................................................................58
7.1 Sentencia INSERT..............................................................................................58
7.1.1 Inserción con SELECT................................................................................59
7.2 Sentencia UPDATE............................................................................................ 61
7.2.1 UPDATE con SELECT................................................................................61
7.3 Sentencia DELETE.............................................................................................62
8 ROLLBACK, COMMIT y AUTOCOMMIT...................................................................62
9 ANEXO:......................................................................................................................65
Comentarios
Aunque estos apuntes sirven como guía de uso de SQL estándar, la base de datos
que se utiliza como referencia fundamental es la base de datos Oracle. Normalmente
se indican siempre las instrucciones para Oracle y para el SQL estándar. En las partes
donde no se indique explícitamente diferencia, significará que Oracle coincide con el
estándar. Sin embargo hay que avisar que todos los ejemplos han sido probados para
Oracle, mientras que no se puede decir lo mismo para SQL estándar.
En el caso de SQL estándar, el software PostgreSQL se ha tenido muy en cuenta ya
que parece el más respetuoso actualmente con el estándar. No obstante es posible
que muchos apartados se refieran sólo a Oracle y sobre todo los detalles de
funcionamiento y resultados no han tenido en cuenta el estándar, sino sólo el
funcionamiento de Oracle.
La razón de utilizar Oracle como base de trabajo se debe a su respeto por SQL
estándar (aunque desde luego no tan estricto como PostgreSQL), es decir que no es
excesivamente diferente; pero fundamentalmente por ser el SGBD de referencia más
importante desde hace ya muchos años. De hecho lo que Oracle aporta de novedoso
en cada versión, acaba formando parte del estándar futuro.
1 Introducción
En un sistema de gestión de bases de datos las operaciones sobre los datos se realizan
a través de consultas formuladas con un lenguaje específico declarativo.
SQL se considera el lenguaje estándar de base de datos relacional. SQL es una
abreviatura de Structured Query Language (Lenguaje de Consulta Estructurado). Pero es
algo más que un lenguaje de consulta, puesto que no sólo ofrece funciones de
recuperación, sino también una diversidad de operaciones de actualización y
manipulación de información y estructura de los datos.
El nacimiento del lenguaje SQL data de 1970 cuando E. F. Codd publica su libro: "Un
modelo de datos relacional para grandes bancos de datos compartidos". Ese libro
dictaría las directrices de las bases de datos relacionales. Apenas dos años después IBM
(para quien trabajaba Codd) utiliza las directrices de Codd para crear el Standard English
Query Language (Lenguaje Estándar Inglés para Consultas) al que se le llamó SEQUEL.
Más adelante se le asignaron las siglas SQL (Standard Query Language, lenguaje
estándar de consulta) aunque en inglés se siguen pronunciando secuel.
En 1979 Oracle presenta la primera implementación comercial del lenguaje. Poco
después se convertía en un estándar en el mundo de las bases de datos avalado por los
organismos ISO y ANSI. En el año 1986 se toma como lenguaje estándar por ANSI de
los SGBD relacionales. Un año después lo adopta ISO, lo que convierte a SQL en
estándar mundial como lenguaje de bases de datos relacionales. En 1989 aparece el
estándar ISO (y ANSI) llamado SQL89 o SQL1. En 1992 aparece la nueva versión
estándar de SQL llamada SQL92. En 1999 se aprueba un nuevo SQL estándar que
incorpora mejoras que incluyen disparadores, procedimientos, funciones y otras
características de las bases de datos objeto-relacionales; dicho estándar se conoce
como SQL99.
La última revisión del estándar es el del año 2016 (SQL2016).
Mas información en https://es.wikipedia.org/wiki/SQL
3 Sublenguajes de SQL
El lenguaje SQL se divide a su vez en tres tipos de lenguajes dependiendo del tipo de
operación que deseamos realizar sobre la Base de Datos. Estos tipos son DDL, DML y
DCL.
DDL (Data Definition Language): Este sublenguaje agrupa los comandos SQL utilizados
para definir, borrar, reemplazar o alterar estructuras de la base de datos.
DML (Data Manipulation Language) Este sublenguaje agrupa los comandos SQL que
permiten realizar consultas y modificaciones, inserciones y borrados sobre las tablas.
DCL (Data Control Language) Este sublenguaje permite establecer derechos de acceso
a los usuarios, comprobaciones de integridad y control de transacciones. Incluye órdenes
para dar y quitar privilegios, así como para completar y abortar transacciones.
En la siguiente tabla podemos ver un resumen de los tipos de lenguajes de SQL con sus
instrucciones principales.
Casi todas las sentencias SQL tienen una forma básica. Todas comienzan con un verbo,
que es una palabra clave que describe lo que hace la sentencia (por ejemplo SELECT,
INSERT, UPDATE, CREATE). A continuación, le siguen una o más cláusulas que
especifican los datos con los que opera la sentencia. Estas también comienzan con una
palabra clave como WHERE o FROM. Algunas son opcionales y otras obligatorias.
Muchas contienen nombres de tablas o de columnas, palabras reservadas, constantes o
expresiones adicionales.
Texto
Sirven para almacenar intervalos de tiempo (no fechas, sino una suma de elementos
de tiempo).
Este tipo de datos almacena años y meses. Tras la palabra YEAR se puede indicar
la precisión de los años (cifras del año), por defecto es de dos.
INTERVAL YEAR TO Para los intervalos de año a mes los valores se pueden indicar de estas formas:
MONTH
Precedencia numérica:
En operaciones que soporten varios tipos de datos numéricos: binary_double es el
que tiene mayor prioridad, seguido de binary_float y por último number. Es decir: Si
alguno de los operandos es binary_double, el resto de los operandos se convierten a
binary_double antes de realizar cualquier operación aritmética. Y así sucesivamente.
De los tipos anteriores, los más utilizados son: VARCHAR2 (cadenas de texto no muy
grandes), DATE (fechas, horas), NUMBER (números), BLOB (ficheros de tipo word,
excel, access, video, sonido, imágenes, etc) y CLOB (cadenas de texto muy grandes).
4.2 Constantes
Texto
Especifica una constante de carácter o un conjunto de caracteres. La sintaxis se
representa mediante el siguiente diagrama:
Entera
Un entero puede almacenar un máximo de 38 dígitos de precisión. Su sintaxis es:
Real
Sintaxis:
Constantes intervalos
Especifica un período de tiempo en términos de años y meses o en días, horas, minutos
y segundos.
Ej: INTERVAL '123-2' YEAR(3) TO MONTH (intervalo de 123 años y
dos meses)
Fecha y hora
Escritas como literal deben seguir el formato DATE 'YYYY-MM-DD' o TIMESTAMP
'YYYY-MM-DD HH24:MI:SS.FF'
Ej: entre 13 y 18
Ej. : 'El nombre es' || ' Juan' se evalúa como 'El nombre es Juan';
Si tienen igual prioridad la asociatividad es de izquierda a derecha. La potencia NOOOOO. Ej: 3^4^5
sería 3^(4^5)
5.1.1 Introducción
Regla para referenciar un objeto:
[<nom_esquema>.]<nombre_objeto>[.<Parte_objeto>]
Si no se es el propietario de la tabla, hay que especificar el propietario delante de la
tabla. SELECT * FROM HR.COUNTRIES; HR PORQ LA
TABLA ESTA EN ESE USUSARIO
SELECT department_name, manager_id FROM hr.departments;
SELECT * FROM regions: EL ASTERISCO ES PARA TODOS LOS
CAMPOS, ES LO MISMO Q PONER region_name, region_id from
Alias del nombre de una tabla:
regions; darle al play !!!! --> sentencia
de ejecucion
FROM <nombre_objeto> <alias>
El alias no es permanente y sólo es válido para este comando. Es útil cuando en el
FROM aparece más de una vez la misma tabla.
No es lo mismo crear un alias de una tabla que un sinónimo ya que éste último
permanece en la base de datos hasta que se borra.
SELECT * FROM jobs jb
WHERE jb.min_salary > 20000;
Permite visualizar la columna con otro nombre. Cuando contiene espacios o caracteres
especiales debe acotarse con doble comillas.
SELECT first_name Nombre, last_name "Los apellidos" FROM employees;
• Lista de tablas: serie de tablas separadas por comas necesarias para procesar la
consulta.
• Condición: sirve para identificar las filas que obtendrá la consulta.
• Lista de expresiones: por las que se agrupan las filas.
• Predicado: filtra las filas devueltas por los agrupamientos.
• Lista de ordenación: indica los nombres de los atributos por los que se pretende
ordenar el resultado de la consulta.
Dentro de la lista de atributos pueden aparecer expresiones, constantes y funciones no
sólo nombres de columnas.
No importa si se usan mayúsculas o minúsculas.
Ejemplo: Devuelve los países cuyo nombre sea mayor que 'Spain'.
SELECT *
FROM countries
WHERE country_name>'Spain';
Usamos el formato por defecto de fecha. Para hacer la condición independiente del
formato de fecha por defecto podríamos utilizar la función TO_DATE de la siguiente
forma:
where hire_date > TO_DATE('2007-01-01', 'yyyy-mm-dd');
Ejemplo: Devuelve los empleados cuyo nombre sea mayor que 'Donald' y menor que
'Stiles' o cuyo id de departamento sea 50.
SELECT *
FROM employees
WHERE (first_name>'Donald' AND first_name<'Stiles') OR department_id=50;
Lista de ordenación:
Asimismo, es posible anidar los criterios. El situado más a la izquierda será el principal.
Ejemplo: Devuelve los empleados ordenados por nombre ascendente y, dentro del
nombre, por apellido descendente
SELECT *
FROM employees
dentro de los de igual
ORDER BY first_name, last_name DESC; nombre ordena los apellidos
ALL: Con la cláusula ALL recuperamos todas las filas, aunque algunas estén repetidas.
Es la opción por omisión.
DISTINCT: Sólo recupera las filas que son distintas.
Ejemplo: Observar las diferencias entre ejecutar la primera consulta y la segunda. La
primera consulta genera muchas filas repetidas.
SELECT department_id
FROM employees
ORDER BY department_id;
Sin embargo, si añadimos a las SELECT el campo employee_id, las dos consultas
devolverían lo mismo ya que al añadir el campo clave no pueden existir filas repetidas.
-- Da igual poner o no poner DISTINCT
SELECT employee_id, department_id
FROM employees
ORDER BY department_id;
Existe un comando muy útil, sobre todo cuando estamos usando SQLPlus, que nos
permite ver la estructura de una tabla. El comando es DESC (de DESCRIBE).
Ejemplo: Muestra la estructura de la tabla locations.
DESC locations;
Mostrará:
Nombre ¿Nulo? Tipo
-------------- -------- ------------
LOCATION_ID NOT NULL NUMBER(4)
STREET_ADDRESS VARCHAR2(40)
POSTAL_CODE VARCHAR2(12)
CITY NOT NULL VARCHAR2(30)
STATE_PROVINCE VARCHAR2(25)
COUNTRY_ID CHAR(2)
También podemos escribir la sentencia de la siguiente forma para así decidir en que
orden se muestran las columnas.
Ejemplo: Muestra el id de la localización, la dirección, ciudad, provincia e id de país para
todas las localizaciones.
SELECT location_id, street_address, postal_code, city, state_province,
country_id
FROM locations;
Ejemplo: Obtener los empleados contratados entre los años 2000 y 2003
SELECT *
FROM employees
WHERE hire_date BETWEEN '01/01/2000' AND '31/12/2003';
IS [NOT] NULL
A la hora de evaluar una condición de tipo relacional o lógica el resultado puede ser
verdadero, falso ó desconocido. Cuando en un WHERE no se produce ninguna fila, o
resulte una tabla vacía se da un valor desconocido.
El resultado de una condición es diferente si es falso o si es desconocido porque:
NO FALSO equivale a VERDADERO
NO DESCONOCIDO no tiene porqué equivaler a VERDADERO.
Ej. : Tabla de comparación de un operando ‘a’ con otro NULL
Para comprobar si algo es nulo o no, solo se usa las condiciones “is NULL” e “is not
NULL”
Ejemplos: nombre IS NULL -- devuelve verdadero si nombre es NULL
Ejemplo: Obtener las localizaciones con el campo provincia a NULL y el campo ciudad
entre 'Geneva' y 'Tokio'
SELECT *
FROM locations
WHERE state_province IS NULL AND city BETWEEN 'Geneva' AND 'Tokio';
Sintaxis:
<exp> [NOT] IN (<lista_de _ctes>)
o
<exp> [NOT] IN (<subselect>)
Este operador resulta mucho más potente con la combinación de subconsultas. Una
subconsulta es una SELECT dentro de otra; este caso se estudiará más adelante.
LIKE
Sintaxis:
nombre_columna [NOT] LIKE <cte_alfanumérica> [ESCAPE char_de_esc]
Ejemplo: Obtener los nombres y apellidos de los empleados cuyo nombre empieza por
P.
SELECT first_name, last_name
FROM employees
WHERE first_name LIKE 'P%';
Ejemplo: Obtener los nombres y apellidos de los empleados cuyo nombre empieza por T
y contengan el carácter a en su interior.
SELECT first_name, last_name
FROM employees
WHERE first_name LIKE 'T%a%';
Actividades propuestas 1
Producto cartesiano:
Cuando listamos más de una tabla en la cláusula FROM sin especificar ninguna
condición que las combine adecuadamente en el WHERE, se produce un producto
cartesiano entra las tablas listadas.
En un producto cartesiano se combinan todas las filas de todas las tablas implicadas
en el FROM: se forman todas las posibles combinaciones de todas las filas de una
tabla con las demás.
En un producto cartesiano de dos tablas, si la primera tabla tiene 10 filas y la segunda
tabla 23, el producto cartesiano generará 230 filas.
Se devuelven en total 100 filas, cada una de las 4 regiones se combina con los 25
países. Al poner * en el SELECT se muestran todas las columnas de las dos tablas.
Como vemos esta información no resulta muy útil. Tenemos que aprender a combinar las
tablas de manera apropiada. Para ello debemos disponer de alguna columna que permita
realizar esta combinación. En el ejemplo que nos ocupa la columna es region_id. Sólo
nos interesan las filas del producto cartesiano que cumplan la condición de que el
region_id de countries coincida con el region_id de regions. En realidad estamos
utilizando la relación del MER, la clave ajena del modelo relacional.
La select que mostraría correctamente la combinación de las dos tablas podría ser:
SELECT *
FROM regions, countries
WHERE regions.region_id = countries.region_id;
A este tipo de operación entre tablas se le denomina JOIN. La sintaxis para las
operaciones tipo join ha evolucionado junto con SQL. Todo lo que se imparte en este
tema es compatible con Oracle; para otros SGBD deberíamos consultar su
documentación.
Cuidado con el campo country_id en la select. Debemos añadir de que tabla mostrarlo
con el alias l o c.
Se pueden añadir condiciones adicionales de búsqueda usando otros operadores.
Ejemplo: Obtener el nombre, apellido, id de trabajo, título o descripción del trabajo para
los empleados con un salario mayor de 10000 dólares.
SELECT e.first_name, e.last_name, e.job_id, j.job_title, e.salary
FROM employees e, jobs j
Notese que la consulta anterior devuelve 106 empleados cuando la tabla de employees
tiene 107.
Outer join:
O combinación externa, amplifica el resultado de una combinación simple. Una
combinación externa recupera todas las filas de la combinación y también aquellas que
no encuentren su correspondiente fila pareja de una tabla a otra.
El operador outer join se representa por un (+) y puede aparecer sólo en un lado de la
expresión: el lado al que le falta información. Una condición que incluye un outer join no
puede usar el operador IN o unirse a otra condición por el operador OR.
Los outer joins pueden ser:
Es un outer join right. Aparece el empleado Kimberely Grant que tiene el campo
department_id a null. Si no usáramos el + sólo obtendríamos 106 empleados.
Ejemplo: Obtener código y el nombre de todos los países, junto con sus localizaciones
(city, street_address y postal_code) existan éstas o no.
SELECT c.country_id, c.country_name, l.city, l.state_address, l.postal_code
FROM countries c, locations l
WHERE l.country_id(+) = c.country_id;
Es un outer join left. Aparecen once países al final que no tienen localizaciones.
Si existieran localizaciones sin países sería (l.country_id a null, no es el caso en nuestros
datos):
Se han utilizado alias de tablas con significado por claridad: emp y jefes
Se han utilizado también alias de columnas por claridad.
Si os fijáis, el jefazo Steven King tiene el campo manager_id a null por lo que no sale en
la consulta anterior. Si hacemos un outer join sí podremos obtenerlo:
SELECT emp.employee_id, emp.first_name, emp.last_name, jefes.employee_id,
jefes.first_name "Nombre jefe", jefes.last_name "Apellido jefe"
FROM employees emp, employees jefes
WHERE emp.manager_id=jefes.employee_id (+);
Establece una relación de igualdad entre las tablas a través de los campos que tengan el
mismo nombre en ambas tablas. No es raro que las únicas columnas con el mismo
nombre entre dos tablas son las que permiten relacionar sus datos.
Ejemplo: Obtener el listado de id, el nombre de la region y el id y nombre de país a la
que pertenece la region. Ordenar por region_name.
SELECT region_id, r.region_name, c.country_id, c.country_name
FROM regions r
NATURAL JOIN countries c
ORDER BY r.region_name;
En este caso se puede hacer el NATURAL JOIN ya que la clave ajena se llama igual que
la clave primaria a la que hace referencia: region_id. En este campo no se puede usar
cualificador (r o c) ya que NATURAL JOIN considera que no hay dos columnas region_id
sino solo una.
NATURAL JOIN solo se puede aplicar a tablas donde las únicas columnas que tienen el
mismo nombre son las que sirven para relacionar las tablas.
JOIN USING
JOIN USING permite asociar tablas indicando las columnas que las relacionan, si estas
tienen el mismo nombre en ambas tablas., A diferencia de NATURAL JOIN no tienen
porque ser las únicas con el mismo nombre.
Ejemplo: Obtener el listado de id, el nombre de la region y el id y nombre de país a la
que pertenece la region. Ordenar por region_name.
SELECT region_id, r.region_name, c.country_id, c.country_name
FROM regions r
JOIN countries c USING(region_id)
ORDER BY r.region_name;
A veces no es solo una columna la que sirve para relacionar, lo cual implica indicar todas
las columnas que relacionan. Ejemplo:
SELECT campo1, campo2, t1.campo3, t2.campo4
FROM tabla1 t1
JOIN tabla2 t2 USING(campo1,campo2);
Esta consulta supone que las tablas tabla1 y tabla2 comparten dos campos con el mismo
nombre: campo1 y campo2
JOIN ON
A veces las tablas se relacionan en formas que no encajan con ninguno de los JOIN
anteriores. Los campos por los que queremos relacionar no tienen el mismo nombre. Si
deseamos mostrar la lista de departamentos con el nombre de su jefe nos encontramos
con que la clave ajena en departments se llama manager_id y la clave primaria de
employees se llama employee_id.
Esta situación no encaja ni en un NATURAL JOIN ni en un JOIN USING. Para esto sirve
JOIN ON.
JOIN ON permite indicar la condición (al estilo de SQL 92) que relaciona las tablas. En
este caso sería:
SELECT d.department_id, d.department_name, d.manager_id, e.first_name,
e.last_name
FROM departments d
JOIN employees e ON (d.manager_id=e.employee_id);
Hay que señalar que cualquier JOIN USING se puede hacer con JOIN ON (sin embargo
esto no ocurre al revés)
Ejemplo: Obtener el listado de id, el nombre de la region y el id y nombre de país a la
que pertenece la region. Ordenar por region_name.
SELECT r.region_id, r.region_name, c.country_id, c.country_name
FROM regions r
JOIN countries c ON(r.region_id=c.region_id)
ORDER BY r.region_name;
JOIN ON sí requiere cualificar las columnas que se relacionan aunque tengan el mismo
nombre.
Podemos hacer un JOIN ON con más de dos tablas:
Ejemplo: Obtener el nombre, apellido, id de trabajo para los empleados, nombre de
departamento y título del trabajo que desempeña el empleado.
SELECT e.first_name, e.last_name, e.job_id, d.department_name, j.job_title
FROM employees e
JOIN departments d ON (e.department_id = d.department_id)
JOIN jobs j ON (e.job_id = j.job_id);
Hay que tener en cuenta que en cualquiera de las consultas anteriores podemos añadir
condiciones adicionales mediante la cláusula WHERE:
SELECT region_id, r.region_name, c.country_id, c.country_name
FROM regions r
NATURAL JOIN countries c
WHERE r.region_name like 'A%'
ORDER BY r.region_name;
Actividades propuestas 2
1. Obtener el nombre, apellido, correo id de trabajo y descripción del trabajo para
todos los empleados que trabajan en el departamento de código 80.
2. ¿Cuál es el empleado que dirige el departamento 100? Mostrar todos sus datos.
3. Obtener los departamentos que están localizados en la ciudad de Seatle.
4. Obtener un listado con todos los departamentos que no tengan ningún
empleado. Debéis utilizar JOIN USING.
5. Obtener un listado con el historial de trabajos de nuestra empresa mostrando
también el nombre de departamento, la descripcion del trabajo y el nombre y
apellido del empleado.
6. Obtener el nombre, apellido, id de trabajo para los empleados que han sido
alguna vez ST_CLERK.
7. Obtener un listado con los países donde no exista ninguna localización. Debéis
utilizar JOIN ON.
8. Obtener las localizaciones de United Kingdom con el campo provincia a nulo.
Debéis mostrar el nombre de región, nombre de país y todos los campos de la
localización.
9. Obtener un listado de todos los trabajos que no aparecen en la tabla job_history.
Debéis utilizar la sintaxis SQL92.,
10. Obtener un listado con todos los nombres y apellidos de los empleados que son
jefes de algún empleado.
11. Obtener la información de los empleados que no tengan jefe.
12. Obtener un listado con todos los empleados que tengan el salario fuera de los
límites mínimo y máximo que marca su tipo de trabajo.
13. Obtener un listado con todos los empleados contratados antes del 2005 y que
sean Shipping Clerk.
14. Obtener un listado con el nombre y apellido del empleado, el nombre del
departamento y su comisión para todos aquellos empleados con la comisión inferior
a 0,1.
Ejemplo: Obtener el salario medio de todos los empleados del departamento 100.
SELECT avg(salary)
FROM employees e
WHERE department_id=100;
Si COUNT recibe como argumento una expresión o columna, ésta podrá ir precedida de
las cláusulas ALL o DISTINCT.
Ejemplo: Obtener cuántos departamentos tienen empleados
SELECT count(DISTINCT e.department_id)
FROM employees e;
Si la select contiene GROUP BY, la lista de atributos a mostrar sólo puede contener los
siguientes tipos de expresiones:
• Constantes.
• Funciones de agrupación o de grupo.
• Expresiones idénticas a las que estarán en la cláusula GROUP BY.
• Expresiones implícitas en las expresiones mencionadas en la select que evalúen el
mismo valor para todas las filas de un grupo.
Las expresiones en la cláusula GROUP BY pueden contener cualquier columna de una
tabla o vista mencionada en el FROM, sin importar que estas columnas estén o no en la
lista de la select.
Los valores nulos en las columnas de agrupamiento se consideran iguales, es decir, se
incluyen en el mismo grupo.
Una vez formados los grupos, para cada uno de ellos se evalúan las expresiones de la
cláusula SELECT. Por tanto, cada grupo produce una fila en la tabla resultante.
Las columnas que no figuren en la cláusula GROUP BY, podrán especificarse en la lista
de atributos de la select sólo en los argumentos de funciones de agrupamiento.
GROUP BY no ordena el resultado de la consulta, para eso tendríamos que utilizar
ORDER BY.
Ejemplo: Obtener el número de empleados que existen en cada departamento.
SELECT department_id, count(employee_id)
FROM employees e
GROUP by department_id;
Notese que count(*) no es válido porque me cuenta el valor null como 1 (1 fila). Tampoco
podemos mostrar e.employee_id ni e.first_name porque no forman parte del group by ni están
en una función de grupo.
Ejemplo: Obtener el número de empleados del departamento que tiene más empleados.
SELECT max(count(e.employee_id))
FROM employees e
GROUP by department_id;
HAVING
Del mismo modo que existe la condición de búsqueda WHERE para filas individuales,
también hay una condición de búsqueda para grupos de filas: HAVING. La cláusula
HAVING se emplea para controlar cuál de los conjuntos de filas se visualiza. Se evalúa
sobre la tabla que devuelve el GROUP BY. No puede existir sin GROUP BY.
La condición es un predicado simple o compuesto, en el que las columnas que participen
y no sean de agrupamiento deberán figurar como argumentos de funciones de
agrupamiento. En la condición también pueden aparecer las funciones agregadas tal
como aparecen en el SELECT.
Ejemplo: Obtener los departamentos que tienen más de 4 empleados.
SELECT department_id, count(employee_id)
FROM employees e
GROUP by department_id
HAVING count(employee_id)>4;
Actividades propuestas 3
1. Obtener el salario máximo para el departamento 80.
2. Mostrar el salario máximo que puede llegar a ganarse en la empresa.
3. Obtener los nombres de departamentos que tengan más de 4 personas
trabajando.
4. Obtener el número de localizaciones que existen en cada país.
5. Obtener el número de localizaciones que existe en cada país pero mostrando
también los países con 0 localizaciones.
6. Obtener un listado con el id de empleado que es jefe y con el número de
empleados que dirige.
7. Obtener un listado con los nombres y apellidos de los empleados que son jefes
de otros empleados y con el número de empleados que dirige.
8. Por cada tipo de trabajo mostrar su id, descripción, número de empleados que
realizan ese trabajo y cuál es el salario máximo de empleado de entre todos los que
desempeñan ese trabajo.
9. Mostrar los departamentos para los que existe algún trabajador que gane igual o
más de salario máximo que establece su tipo de trabajo.
10. Mostrar el id de país y el nombre de aquellos países que tengan localizados más
de un departamento.
5.5 Subconsultas
Es una sentencia SELECT que está incluida en una cláusula de otra sentencia SQL
(FROM (de una select o delete) o WHERE, HAVING).
Ejemplo: ¿Qué empleados son del mismo departamento que el empleado de id 100?
Para averiguar esto se necesitan dos consultas:
• Subconsulta: que averigüe el departamento del empleado de id 100.
• Consulta externa: hallar los empleados que sean de ese departamento.
Primero se ejecuta la subconsulta y luego se usa como valor para la consulta principal.
SELECT *
FROM employees
WHERE department_id = (SELECT department_id
FROM employees WHERE employee_id = 100)
Tipos de subconsultas:
• Monofila
• Multifila
• Multicolumna
Errores comunes:
• Que la subconsulta mono-fila contenga un group by que devuelva más de una fila.
• Que la subconsulta no devuelva ninguna fila con lo que el resultado de la principal
tampoco.
Sintaxis: Siendo X una expresión e Y una expresión que puede ser una subconsulta
Nota: Estos operadores pueden usarse con un subconsulta o con una lista de
expresiones separadas por comas.
Ejemplo: Obtener la lista de todos los id de empleados que son jefe de alguien.
SELECT DISTINCT manager_id
FROM employees;
Ejemplo: Obtener la lista de todos los id de empleados que son jefes actualmente y que
aparecen en el histórico de empleados.
SELECT DISTINCT employee_id
FROM job_history
WHERE employee_id IN (SELECT DISTINCT manager_id
FROM employees); -- =SOME o =ANY
Ejemplo: Obtener los datos de los empleados que están contratados por primera vez en
la empresa.
SELECT *
FROM employees
WHERE employee_id NOT IN (SELECT DISTINCT employee_id
FROM job_history); -- !=ALL
Ejemplo: Obtener toda la información de los empleados junto con el departamento para
aquellos empleados que han estado contratados alguna vez.
SELECT *
FROM employees e, departments d
WHERE (e.employee_id, d.department_id) = ANY (SELECT DISTINCT employee_id,
department_id FROM job_history);
Si se detallan varios campos en la cláusula WHERE, deben encerrarse entre paréntesis,
y han de coincidir en número y tipo de datos con los de la sentencia SELECT de la
consulta interior. Cada columna de la cláusula WHERE se referirá a la correspondiente
columna de la subconsulta.
La subconsulta devuelve para cada fila que se recupere de la consulta más externa el
máximo salario del departamento que se está recuperando en la consulta externa; para
referenciar a dicho departamento se necesita el alias e usado en la tabla de la consulta
externa.
Ejemplo: ¿Qué empleados tienen el salario máximo de su tipo de trabajo?
SELECT *
FROM employees e
WHERE salary = (SELECT max_salary
FROM jobs
WHERE job_id=e.job_id);
Nótese como estamos pasando el dato job_id a la subconsulta por medio del uso del
alias e.
UNION
SELECT c.*
FROM countries c
WHERE c.country_id NOT IN (SELECT DISTINCT country_id FROM locations)
AND c.region_id = 4;
UNION ALL:
Devuelve todas las filas de ambas consultas incluyendo todas las entradas duplicadas.
INTERSECT:
Devuelve todas las filas comunes eliminando duplicados.
MINUS:
Devuelve todas las filas del resultado de la primera consulta menos las contenidas en el
resultado de la segunda consulta.
Actividades propuestas 4
1. Muestra los datos (nombre, apellido, id oficio, salario y fecha de alta) de aquellos
empleados que desempeñen el mismo oficio que Renske Ladwig o que tengan un
salario mayor o igual que Janette King.
2. Mostrar los datos del empleado jefe del departamento Administration.
3. Obtener la lista de todos los departamentos cuyo salario medio sea superior a la
media del salario medio de los departamentos.
4. Obtener aquellos nombres y apellidos de empleados cuyo oficio sea alguno de
los oficios que hay en el departamento 50.
5. Obtener los datos de los empleados cuyo salario sea menor a cualquier salario
de los empleados del departamento 80.
6. Obtener los datos de los empleados que trabajan en Toronto, Tokyo o Roma.
7. Consulta los nombres, apellidos y oficios de todos los empleados del
departamento 80 cuyo trabajo sea idéntico al de cualquiera de los empleados del
departamento de IT.
8. Obtén el nombre y apellido de los empleados con el mismo oficio y salario que
Patrick Sully.
9. Muestra en pantalla el nombre, apellido, oficio y salario de los empleados del
departamento de Alana Walsh que tengan su mismo salario.
10. Obtén los datos de los departamentos que no tengan empleados.
11. Obtén los datos de los departamentos que tengan empleados.
12. Obtén todos los datos de los departamentos con empleados excepto aquellos
departamentos que estén localizados en la región 3.
13. Obtén todos los datos de los empleados que son ST_CLERK y que han sido
13. select *From employees
ST_CLERK here job_id='SR_CLERK'
NION
14. Obtén todos los departamentos en cuyo historial de empleados tengamos al
ELECT E.*ßROM JOB_HISTORY J
menos 2 trabajadores junto con los
OIN EMPLOYEES departamentos
E ON que tienen
(E.EMPLOYEES_ID más de 7 empleados.
= J.EMPLOYEE_ID
HERE J.JOB_ID='ST_CLERK');
14. SELECT D.DEPARTEMNT_ID, DEPARTMENT_NAME, MANAGER_ID, LOCATION_ID
FROM JOB_HISTORY J
JOIN DEPARTMENT D ON (D.DEPARMENT_ID = J.DEPARTMENT_ID)
GRUP BY D.DEPARTEMNT_ID, DEPARTMENT_NAME, MANAGER_ID, LOCATION_ID
HAVING COUNT (EMPLOYEE_ID)>=2
UNION
SELECT D.*
FROM DEPARTMENT D
MLLS. Dpto. Informática. IES San Sebastián Página 44 de 67
JOIN EMPLOYEE E ON (D.DEPARMET_ID=E.DEPARTMENT.ID)
GRUP BY D.DEAPRT,MEMNT_ID, D.DEAPRTMENT_NAME, D.MANAGER_ID, D.LOCATION_ID
6 Funciones
Las funciones se usan dentro de expresiones y actúan con los valores de las columnas,
variables o constantes.
Si se llama a una función con un argumento de otro tipo que el esperado, Oracle intenta
su conversión al tipo adecuado de forma implícita.
Si se llama a una función con un argumento nulo, la función devuelve nulo (excepto NVL,
CONCAT , REPLACE). Es posible el anidamiento de funciones. Las funciones de SQL se
clasifican en :
1. Escalares (o de fila simple )
a) Numéricas
b) Carácter
c) De fecha y tiempo
d) De conversión
e) Otras
2. Agregadas o de agrupación. Ya estudiadas.
En Oracle existe una tabla denominada DUAL muy útil para comprobar el resultado de
las funciones. Su descripción es la siguiente:
Tiene una sola fila, por lo que podemos hacer pruebas como la que sigue:
SELECT abs(-100) FROM dual;
Devolvería una sóla fila de una columna llamada abs(-100) y con valor 100.
Funciones numéricas
sql> select mod(25,3) from dual;
Devuelve el resto resultante de dividir valor entre
mod(25,3) 1
mod(valor) divisor. Si el divisor es igual a cero, entonces, se
sql> select mod(24,3) from dual;
devuelve valor.
mod(24,3) 0
sql> select power(2,4) from dual;
power(valor, exponente) El valor se eleva a la potencia del exponente.
power(2,4) 16
sql> select round(456.789,3) from dual; Devuelve valor redondeado a precision decimales. Si
round(456.789,3) 456,789 precision es negativo, el redondeo de dígitos se lleva a
round(valor, precision)
sql> select round(456.789,2) from dual; cabo a la izquierda del punto decimal. Si se omite
round(456.789,2) 456,79 precision, devuelve valor con 0 decimales y redondeado.
Devuelve un número que indica si el valor es positivo o
sql> select sign(-22) from dual;
negativo:
sign(-22) -1
sign (valor) Valor > 0, devuelve 1
sql> select sign(8) from dual;
Valor < 0, devuelve -1
sign(8) 1
Valor = 0, devuelve 0
sql> select sqrt(25) from dual;
sqrt(25) 5
sqrt(valor) Devuelve la raíz cuadrada de valor.
sql> select sqrt(26) from dual;
sqrt(26) 5,09901951
Devuelve el valor truncado con la precisión especificada.
Si precisión es positiva, truncará dicho número de
sql> select trunc(4.789,2) from dual;
posiciones a la derecha del punto decimal. Si precisión es
trunc(4.789,2) 4,78
trunc(valor, precisión) negativa, trucará dicho número de posiciones a la
sql> select trunc(456.789, -2) from dual;
izquierda del punto decimal. Si precisión no se
trunc(456.789,-2) 400
especifica, se supondrá el valor de cero, con lo que se
truncará en el punto decimal.
sql> select acos(1) from dual;
acos(1) 0
acos(valor) Devuelve el arcocoseno de valor.
sql> select acos(0) from dual;
acos(0) 1,57079633
sql> select asin(1) from dual;
asin(valor) Devuelve el arcoseno de valor.
asin(1) 1,57079633
sql> select atan(1) from dual;
atan(valor) Devuelve la arcotangente de valor.
atan(1) ,785398163
sql> select cosh(6) from dual;
cosh(valor) Devuelve el coseno hiperbólico de valor.
cosh(6) 201,715636
sql> select exp(2) from dual; Devuelve el resultado de elevar el número e al exponente
exp(valor)
exp(2) 7,3890561 valor.
sql> select ln(95) from dual;
ln (valor) Devuelve el logaritmo neperiano de valor.
ln(95) 4,55387689
sql> select log(10, 1000) from dual;
log(base, valor) Devuelve el logaritmo en base introducida, de valor.
log(10,1000) 3
sql> select sin(5) from dual;
sin(valor) Devuelve el seno de valor.
sin(5) -,95892427
sql> select sinh(4) from dual;
sinh(valor) Devuelve el seno hiperbólico.
sinh(4) 27,2899172
sql> select tan(6) from dual;
tan(valor) Devuelve la tangente de valor.
tan(6) -,29100619
sql> select tanh(15) from dual;
tanh(valor) Devuelve la tangente hiperbólica.
tanh(15) 1
Funciones de cadena
Devuelve una porción de cadena,
select substr(’abcdefg’,3,4) from dual; empezando en el carácter de la posición
substr(cadena,valor1,[valor2])
cdef indicado valor1 de cadena, y con una
longitud especificada por valor2.
select ascii(’q’) from dual;
ascii(cadena) Devuelve el código ASCII de cadena.
81
Convierte caracteres de una cadena en
caracteres diferentes, según un plan de
sustitución marcado por el usuario.
Devuelve 'cad1' con los caracteres
translate (cad1, cad2, cad3)
encontrados en 'cad2' y sustituidos por los
caracteres de 'cad3'. Cualquier carácter que
no esté en la cadena 'cad2' permanece como
estaba.
Oracle puede almacenar datos de tipo fecha (DATE) y posee una interesante utilidad
para formatear las fechas de cualquier manera que se pueda concebir. Tiene un formato
por omisión: 'DD/MM/YYYY', pero con la función TO_CHAR es posible mostrar las fechas
de cualquier modo. Los literales de fecha deben encerrarse entre comillas simples.
Ejemplo: '18/11/2005'.
Recordemos que el tipo de datos DATE se almacena en un formato especial que incluye
Siglo/Año/Mes/Día/Hora/Minutos/Segundos.
Hay que hacer una observación: el nombre del mes aparece en minúscula porque en el
formato se definió month en minúscula, pero también puede aparecer en mayúscula o
con la primera letra mayúscula y las siguientes en minúsculas. Las opciones para month
son las siguientes: si el nombre de mes es Enero, Month produce Enero, month produce
enero, MONTH produce ENERO. Lo mismo ocurre con day y dy.
SELECT TO_CHAR(hire_date, 'mon ddd y yyy')
FROM employees
WHERE department_id=80;
Ahora la fecha de alta aparece con el nombre del mes con tres letras (mon), el número
de día del año (ddd), el último dígito del año (y) y los tres últimos dígitos del año (yyy).
Por defecto, el formato para la fecha viene definido por el parámetro NLS_TERRITORY,
que especifica el idioma para el formato de la fecha, los separadores de miles, el signo
decimal y el símbolo de la moneda. Este parámetro se inicializa al arrancar Oracle. Para
el idioma español, el valor de este parámetro es: NLS_TERRITORY=SPAIN.
Podemos cambiar el valor por omisión para la fecha con el parámetro
NLS_DATE_FORMAT, usando la orden ALTER SESSION. Por ejemplo, para cambiar el
formato de la fecha y que aparezca de la siguiente manera: día/nombre mes/ año
hora:minutos:segundos utilizaremos la siguiente sentencia:
ALTER SESSION SET NLS_DATE_FORMAT='DD/month/YYYY HH24:MI:SS';
SYSDATE
También podemos cambiar el lenguaje utilizado para nombrar los meses y los días con el
parámetro NLS_DATE_LANGUAGE.
ALTER SESSION SET NLS_DATE_LANGUAGE=French;
SELECT TO_CHAR(sysdate,'"Hoy es " day "," dd " de " month " de " yyyy')
"Fecha" FROM DUAL;
Para consultar los parámetros NLS de nuestra sesión podemos ejecutar la siguiente
sentencia SQL:
SELECT *
FROM NLS_SESSION_PARAMETERS;
Supongamos, por ejemplo, que queremos definir como carácter de los miles el asterisco
(*) y como carácter decimal la barra (/). Hemos de usar el parámetro
NLS_NUMERIC_CHARACTERS con ALTER SESSION:
ALTER SESSION SET NLS_NUMERIC_CHARACTERS='/*';
Sesión modificada.
Los valores para el carácter decimal y de los miles permanecerán hasta que el usuario
finalice la sesión o hasta que el usuario aplique de nuevo la orden ALTER SESSION para
cambiar estos caracteres.
Ejemplo: Cambia el formato de la fecha para que aparezca el año con cuatro dígitos:
ALTER SESSION SET NLS_DATE_FORMAT='DD/MM/YYYY';
Convertir una cadena a tipo DATE:
SELECT TO_DATE('01012006') FROM DUAL;
01/01/2006
Cuando en la orden TO_DATE no se indica el formato, una cadena de caracteres será
convertida a fecha sólo si está en el formato que tenga la fecha del sistema. En el
siguiente ejemplo no se convierte la cadena a tipo fecha porque no está en el formato
'DDMMYYYY' definido en la sesión para la fecha:
SELECT TO_DATE('010106') FROM DUAL;
ERROR en línea 1: ORA-01861: el literal no coincide con la cadena de formato
Lo correcto sería:
SELECT TO_DATE('01012006') FROM DUAL;
Ejemplo: Obtén el nombre del mes a partir de la cadena '01012007' (antes hay que
convertir la cadena a tipo fecha):
SELECT TO_CHAR(TO_DATE('01012007','ddmmyyyy'), 'Month') "MES" FROM DUAL;
TO_DATE y TO_CHAR son similares; la diferencia que los separa estriba en que
TO_DATE convierte una cadena de caracteres en una fecha y TO_CHAR convierte una
fecha en una cadena de caracteres. Ambas pueden utilizar las máscaras de formato de
fechas.
Una columna no-NULL indica que nunca puede estar vacía para ninguna fila. Si una
columna no tiene un valor en al menos una fila, entonces se dice que puede contener
NULL (valores nulos).
Todos los operadores, excepto la concatenación, con un operando NULL, dan como
resultado NULL.
Al ejecutar la sentencia, Oracle emite un mensaje (1 fila creada.) con el que indica que la
fila se ha insertado correctamente.
Observamos en esta sentencia que:
• Las columnas a las que damos valores se identifican por su nombre.
• La asociación columna-valor es posicional.
• Los valores que se dan a las columnas deben coincidir con el tipo de dato definido en la
columna.
• Los valores constantes de tipo carácter han de ir encerrados entre comillas simples (' ')
(los de tipo fecha, también).
Ahora no especificamos los nombres de las columnas por lo que los valores tendremos
que darlos todos y en el orden en el que se han definido en la tabla countries.
Especificando el nombre de las columnas puedo especificar, si quiero, los valores en un
orden diferente al de la creación de la tabla:
INSERT INTO countries (region_id, country_name, country_id)
VALUES (1, 'Spain', 'ES');
Cuando programamos una aplicación esta sería la práctica más recomendable ya que
garantizamos que nuestra sentencia INSERT no dependa del orden de columnas original
de la tabla countries. Este orden podría cambiar si el administrador de la base de datos
modificara la sentencia CREATE de countries o cambiara su diseño introduciendo o
eliminando alguna columna de la tabla.
Como en la tabla countries los campos region_id y country_name pueden tomar valores
nulos sería posible insertar filas en la misma de las siguientes formas:
INSERT INTO countries
VALUES ('XX', 'Xxxx', NULL);
En las dos últimas sentencias los campos no especificados toman el valor nulo de forma
automática.
Ejemplo: Vamos a crear en la tabla job_history las filas necesarias para que todos los
empleados del departamento 30 figuren como que ya estuvieron contratados en su
mismo puesto actual desde el día 1 de enero del 2000 hasta el día 10 de diciembre del
2001.
INSERT INTO job_history (employee_id, start_date, end_date, job_id,
department_id)
SELECT employee_id, TO_DATE('01/01/2000','dd/mm/yyyy'),
TO_DATE('10/12/2001','dd/mm/yyyy'),job_id,department_id
FROM employees
WHERE department_id=30;
Ejemplo: Insertar un empleado llamado Ana Quiroga, con id de empleado 1112 y
[email protected] de correo en la tabla empleados. Los restantes datos del nuevo empleado
serán los mismos que los de James Marlow y la fecha de alta será la fecha actual.
INSERT INTO employees
SELECT 1112, 'Ana', 'Quiroga', '[email protected]', phone_number, SYSDATE,
job_id, salary, commission_pct, manager_id, department_id
FROM employees
WHERE first_name='James' AND last_name='Marlow';
UPDATE NombreTabla
SET (columna1, columna2, ...) = (SELECT col1, col2, ...)
WHERE condición;
UPDATE NombreTabla
SET columna1 = (SELECT col1 ...), columna2 = (SELECT col2 ...)
WHERE condición;
Ejemplo: Asigna el salario y comisión del empleado Julia Nayer a los empleados del
departamento 30.
UPDATE employees SET (salary, commission_pct) = (SELECT salary, commission_pct
FROM employees WHERE first_name='Julia' AND last_name='Nayer')
WHERE department_id=30;
Ejemplo: Divide el salario a la mitad y pon la comisión a 0 para aquellos empleados que
pertenecen al departamento que tiene más empleados.
UPDATE employees SET salary = salary/2, commission_pct = 0
WHERE department_id =
Ejemplos:
Borramos todos los departamentos con id superior a 210
DELETE FROM departments WHERE department_id > 210;
o
DELETE job_history;
SQL*Plus e iSQL*Plus permiten validar automáticamente las transacciones sin tener que
indicarlo de forma explícita. Para eso sirve el parámetro AUTOCOMMIT. El valor de este
parámetro se puede mostrar con la orden SHOW, de la siguiente manera:
SQL> SHOW AUTOCOMMIT;
autocommit OFF
OFF es el valor por omisión, de manera que las transacciones (INSERT, UPDATE y
DELETE) no son definitivas hasta que no hagamos COMMIT. Si queremos que INSERT,
UPDATE y DELETE tengan un carácter definitivo sin necesidad de realizar la validación
COMMIT, hemos de activar el parámetro AUTOCOMMIT con la orden SET:
SQL> SET AUTOCOMMIT ON;
SQL> SHOW AUTOCOMMIT;
autocommit IMMEDIATE
COMMIT implícito
Hay varias órdenes SQL que fuerzan a que se ejecute un COMMIT sin necesidad de
indicarlo:
ROLLBACK automático
Si, después de haber realizado cambios en nuestras tablas, se produce un fallo del
sistema (por ejemplo, se va la luz) y no hemos validado el trabajo, Oracle hace un
ROLLBACK automático sobre cualquier trabajo no validado. Esto significa que tendremos
que repetir el trabajo cuando pongamos en marcha la base de datos.
9 ANEXO:
Soluciones actividades:
Actividades propuestas 2
1. Obtener el nombre, apellido, correo, id de trabajo y descripción del trabajo para todos
los empleados que trabajan en el departamento de código 80.
SELECT first_name, last_name, email, job_id, job_title
FROM employees e
JOIN jobs j USING(job_id)
WHERE department_id=80;
2. ¿Cuál es el empleado que dirige el departamento 100? Mostrar todos sus datos.
select e.*
SELECT e.* from employees e
FROM employees e, departments d join departments d on (e.employee_id =
WHERE e.employee_id = d.manager_id AND d.department_id=100; d.manager_id)
where d.department_id = 100;
Actividades propuestas 3
1. Obtener el salario máximo para el departamento 80.
SELECT max(salary)
FROM EMPLOYEES
WHERE department_id=80;
2. Mostrar el salario máximo que puede llegar a ganarse en la empresa.
SELECT max(max_salary)
FROM JOBS;
3. Obtener los nombres de departamentos que tengan más de 4 personas trabajando.
SELECT department_id, department_name
FROM departments d
JOIN employees e USING (department_id)
GROUP BY department_id, department_name
HAVING count(e.employee_id)>4;
4. Obtener el número de localizaciones que existen en cada país.
(l.country_id), c.county_name
SELECT l.country_id, count(location_id)
FROM locations l locations l
riggth join countries c on (l.country_id=c.country_id)
GROUP BY l.country_id;
c.countr_id,
5. Obtener elc.countrty_name;
número de localizaciones que existe en cada país pero mostrando también
los países con 0 localizaciones.
SELECT c.country_id, c.country_name, COUNT(l.location_id)
FROM countries c
LEFT OUTER JOIN locations l ON(l.country_id=c.country_id)
GROUP BY c.country_id, c.country_name;
6. Obtener un listado con el id de empleado que es jefe y con el número de empleados
que dirige.
SELECT count(e1.employee_id), e1.manager_id
FROM employees e1
group by e1.manager_id;
7. Obtener un listado con los nombres y apellidos de los empleados que son jefes de otros
empleados y con el número de empleados que dirige. select jefe.employee_id,
SELECT count(e1.employee_id), e1.manager_id, e2.first_name, e2.last_name
jefe.first_name,
FROM employees e1, employees e2 count(employee_id),
jefe.last_name
WHERE e1.manager_id = e2.employee_id (+)
GROUP BY e1.manager_id, e2.first_name, e2.last_name; from employees jefe
join employees e
on(jefe.employee_id=e.mana
Otra forma de ejecución más rápida ger_id)
group by jefe.employee_id,
jefe.first_name,
SELECT count(e1.employee_id), e1.manager_id, (select first_name || jefe.last_name;
' ' ||
last_name from employees e2 where e2.employee_id=e1.manager_id) Nombre
FROM employees e1
group by e1.manager_id;
8. Por cada tipo de trabajo mostrar su id, descripción, número de empleados que realizan
ese trabajo y cuál es el salario máximo de empleado de entre todos los que
SELECT j.job_id,
desempeñan ese trabajo. j.job_title,
count(e.employee_id),
SELECT j.job_id, j.job_title, count(e.employee_id), max(e.salary) max(e.salary)
FROM JOBS J
FROM jobs j, employees e LEFT JOIN EMPLOYEES E ON
WHERE j.job_id = e.job_id (+) (J.JOB_ID=E.JOB_ID)
GROUP BY J.JOB_ID,
GROUP BY j.job_id, j.job_title,j.max_salary; J.JOB_TITTLE
9. Mostrar los departamentos para los que existe algún trabajador que gane igual o más
de salario máximo que establece su tipo de trabajo.
SELECT DISTINCT e.department_id
10. Mostrar el id de país y el nombre de aquellos países que tengan localizados más de un
departamento.
select c.country_id, country_name, count (location_id)
SELECT country_id, count(d.department_id) from location l
join countries c on (c.country_id = l.country_id)
FROM departments d group by c.country_id, country_name
having count (location_id)>1;
JOIN locations l USING (location_id)
JOIN countries c USING (country_id)
GROUP BY country_id
HAVING count(d.department_id)>1
Actividades propuestas 4
1. Muestra los datos (nombre, apellido, id oficio, salario y fecha de alta) de aquellos
empleados que desempeñen el mismo oficio que Renske Ladwig o que tengan un
salario mayor o igual que Janette King.
SELECT first_name, last_name, job_id, salary, hire_date
FROM employees
WHERE job_id = (SELECT job_id
FROM employees WHERE first_name = 'Renske' and last_name='Ladwig')
OR salary >= (SELECT salary
FROM employees WHERE first_name = 'Janette' and last_name='King');
2. Mostrar los datos del empleado jefe del departamento Administration.
SELECT *
FROM employees
WHERE employee_id = (SELECT manager_id
FROM departments WHERE department_name ='Administration') ;
3. Obtener la lista de todos los departamentos cuyo salario medio sea superior a la media
del salario medio de los departamentos. SELECT department_id
FROM employees
SELECT department_id, avg(salary) GROUP BY department_id
FROM employees HAVING avg(salary)>(SELECT
GROUP BY department_id avg(avg(salary)
FROM employees
HAVING avg(salary)>(SELECT avg(avg(salary))FROM employees GROUP
e BY
department_id); GROUP BY department_id);
4. Obtener aquellos nombres y apellidos de empleados cuyo oficio sea alguno de los
oficios que hay en el departamento 50. SELECT first_name, last_name,
deptrme_id. job_id
SELECT first_name||' '||last_name FROM employees
FROM employees WHERE job_id IN (SELECT job_id
WHERE job_id IN (SELECT job_id FROM employees WHERE
department_id=50);
FROM employees WHERE department_id=50);
5. Obtener los datos de los empleados cuyo salario sea menor a cualquier salario de los
empleados del departamento 80.
SELECT *
FROM employees
WHERE salary <ALL (SELECT salary
FROM employees WHERE department_id=80);
6. Obtener los datos de los empleados que trabajan en Toronto, Tokyo o Roma.
select *
from employees e
join departments d on (d.department_id= e.departmen_id)
MLLS. Dpto. Informática. IES San Sebastián Página 66 de 67
join locations l on (l.location_id = d.location_id)
where city in ('Toronto', 'Tokyo', 'Roma');
U.D. 4 Manipulación de datos en SQL 1º ASIR-GBD. 2022-2023
7. Consulta los nombres, apellidos y oficios de todos los empleados del departamento 80
cuyo trabajo sea idéntico al de cualquiera de los empleados del departamento de IT.
8. Obtén el nombre y apellido de los empleados con el mismo oficio y salario que Patrick
Sully.
SELECT first_name, last_name
FROM employees
WHERE (job_id, salary) =
(SELECT job_id, salary FROM employees WHERE first_name ='Patrick' AND
last_name='Sully');
O también: