Está en la página 1de 83

Introducción DDL DML Select Group by Joins Otros Biblio

Introducción a SQL

Luis Valencia Cabrera (lvalencia@us.es)

Research Group on Natural Computing


Departamento de Ciencias de la Computación e Inteligencia Artificial
Universidad de Sevilla

02-12-2020, Bases de Datos

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

SQL

SQL (Structured Query Language) es el lenguaje estándar de


las bases de datos relacionales. Es un lenguaje declarativo que
permite especificar diversos tipos de operaciones sobre éstas.
Es capaz de conjugar las operaciones del álgebra y el cálculo
relacional con operadores adicionales, y definir ası́ consultas
para recuperar o modificar información de bases de datos, ası́
como hacer cambios en ellas.
Pero no sólo incluye consulta. SQL está compuesto por
comandos, cláusulas, operadores y funciones de agregado. En
conjunto, disponemos de instrucciones para definir (crear y
modificar el esquema), mantener (insertar, actualizar,
eliminar ) y consultar BBDD relacionales.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Origen

1970: E.F. Codd (IBM) presenta modelo relacional.


Junto al modelo teórico, propuso el lenguaje DSL/Alpha.
IBM creó versión simplificada: SQUARE.
Más tade lanzaron SEQUEL1 , mejora de SQUARE.
Finalmente, SEQUEL (Structured English Query Language) se
renombró como SQL.
Desde 1986 se han ido sucediendo distintas versiones del
estándar ANSI/ISO SQL, ampliamente conocido como
Structured Query Language.
1
Donald D. Chamberlin and Raymond F. Boyce. 1974. SEQUEL: A
structured English query language. In Proceedings of the 1974 ACM
SIGFIDET (now SIGMOD) workshop on Data description, access and control
(SIGFIDET ’74). ACM, New York, 249–264.
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

SGBD relacionales usando SQL


Sistemas comerciales de Gestión:
Oracle Database de Oracle Corporation
SQL Server de Microsoft
DB2 Universal Database de IBM
Sybase Adaptive Server de Sybase

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

SGBD relacionales usando SQL


Sistemas comerciales de Gestión:
Oracle Database de Oracle Corporation
SQL Server de Microsoft
DB2 Universal Database de IBM
Sybase Adaptive Server de Sybase
¿MS Access?

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

SGBD relacionales usando SQL


Sistemas comerciales de Gestión:
Oracle Database de Oracle Corporation
SQL Server de Microsoft
DB2 Universal Database de IBM
Sybase Adaptive Server de Sybase
¿MS Access? Cubre gran parte de la funcionalidad del núcleo
del estándar, pero con variaciones en la sintaxis de algunos
aspectos, y quedando otras partes del estándar no cubiertas.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

SGBD relacionales usando SQL


Sistemas comerciales de Gestión:
Oracle Database de Oracle Corporation
SQL Server de Microsoft
DB2 Universal Database de IBM
Sybase Adaptive Server de Sybase
¿MS Access? Cubre gran parte de la funcionalidad del núcleo
del estándar, pero con variaciones en la sintaxis de algunos
aspectos, y quedando otras partes del estándar no cubiertas.
Sistemas de código abierto:
Mysql → MariaDB
PostgreSQL
SQLite
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Comandos

Los tipos de comandos en SQL se agrupan en dos categorı́as o


sub-lenguajes:
DDL (Definition Data Language): permite definir el esquema
de bases de datos, creando relaciones (tablas), campos e
ı́ndices, o modificando las definiciones existentes.
DML (Data Maniplation Language): permiten generar
consultas para ordenar, filtrar y extraer datos de la base de
datos, ası́ como insertar, modificar y eliminar registros de las
tablas.
Además está DCL, con comandos de control y seguridad de datos,
que gobiernan los privilegios de los usuarios, los controles de
acceso, ...

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Un ejemplo de DDL: creación de esquemas


Palabra reservada CREATE

El estándar SQL no dispone exactamente de sentencia de


creación de base de datos como tal.
En su lugar, define de una sentencia de creación de esquemas:
CREATE SCHEMA. Con la creación de esquemas podemos
agrupar un conjunto de elementos de la base de datos que son
propiedad de un usuario.
Conceptualmente, podemos entender que la BD contendrá
tanto la definición de los datos como los registros, logs... El
esquema únicamente establecerá la definición de la base de
datos, plasmando el diseño lógico en el SGBD concreto
especificando las relaciones (tablas) y otros objetos
relacionados (como las vistas, por ejemplo.)

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Creación de Bases de Datos

No obstante, la mayorı́a de SGBD incorporan sentencias de


creación de bases de datos como CREATE DATABASE. En el
caso de MySQL, lo define como sinónimo de CREATE SCHEMA.
Además de creación, dentro de DDL tenemos instrucciones
para eliminación; por ejemplo, podemos borrar un esquema o
una base de datos mediante DROP SCHEMA, e igualmente los
SGBD suelen incorporar DROP DATABASE.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Juegos de caracteres

La codificación de caracteres nos permite introducir sı́mbolos


propios del castellano que no corresponden a la codificación
internacional (por ejemplo la ñ).
En MySQL, podemos configurar el juego de caracteres para
toda la base de datos; por ejemplo:
CREATE DATABASE libros character set utf8;
También podemos hacer lo propio con un campo (columna),
añadiendo el juego de caracteres a continuación del tipo:
descripcion VARCHAR(50) character set utf8
Los juegos más comunes son latin1 y utf8

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Comandos DDL

CREATE TABLE, utilizado para crear tablas nuevas


DROP TABLE empleado para eliminar tablas
• Por ejemplo DROP TABLE 'ALUMNOS';
ALTER TABLE sirve para modificar tablas,
agregando/eliminando campos o cambiando su definición
Veamos algunos ejemplos
Para una descripción detallada de las instrucciones SQL
correspondientes se recomienda consultar este documento

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Creación de una tabla


Definición general

CREATE TABLE tabla (


definición de campos,
claves y restricciones
);

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Definición de campos
Tipos de datos

Definición:
nombre_campo tipo marcadores
Tipos:
CHAR(n) Cadenas longitud fija hasta n caracteres.
VARCHAR(n) Cadenas longitud variable hasta n caracteres.
INTEGER, BIGINT, SMALLINT, . . . Enteros.. . .
REAL Número real
DATE Fechas. Están compuestas de: YEAR, MONTH y DAY.
TIME Horas. Están compuestas de HOUR, MINUTE y SECOND.
. . . y muchos más (varı́an según el SGBD).

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Marcadores y restricciones

AUTO_INCREMENT - Autonumérico, secuencial que va


asignando el entero siguiente al máximo valor almacenado
para el campo.
DEFAULT val - Establece un valor por defecto al campo.
NOT NULL - No puede contener valores nulos.
PRIMARY KEY - El campo es la clave primaria no compuesta.
REFERENCES tabla [(campo)] - Clave ajena no compuesta.
CHECK (cond.) - El campo debe cumplir una condición.2

2
Disponible dependiendo del SGBD y su versión
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Claves compuestas y restricciones

PRIMARY KEY (campos) - Clave primaria (compuesta o no).


FOREIGN KEY (campos) REFERENCES tabla [(campos)] -
Clave ajena (compuesta o no).
CHECK (cond.) - El campo debe cumplir una condición.3
Tanto a las claves primarias y ajenas como a los chequeos de
condición se les puede anteponer la partı́cula
CONSTRAINT nombre, para nombrar la restricción.

3
Disponible dependiendo del SGBD y su versión
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Creación de una tabla


Ejemplo básico

CREATE TABLE PRODUCTOS (


codigo_producto INTEGER AUTO_INCREMENT,
nombre_producto VARCHAR(20) UNIQUE NOT NULL,
tipo VARCHAR(20),
descripcion VARCHAR(50),
precio REAL DEFAULT 1.0,
fabrica INTEGER DEFAULT NULL,
PRIMARY KEY (codigo_producto),
FOREIGN KEY (fabrica) REFERENCES FABRICAS(id_fabrica)
ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT precio CHECK (precio>5)
);

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Comandos ALTER

Uso de ADD, MODIFY y DROP para campos.


ALTER TABLE t1 ADD proveedor VARCHAR(50);
ALTER TABLE t1 MODIFY tipo INTEGER;
ALTER TABLE t1 DROP descripcion;
Adición de restricciones, claves, etc.4
ALTER TABLE t1 ADD CONSTRAINT FK1
FOREIGN KEY (c1) REFERENCES t2;

4
Más información en esta web.
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Comandos DML

SQL define cuatro sentencias de manipulación de datos principales:


INSERT, para insertar registros en la base de datos
UPDATE Encargado de modificar los valores de los campos
indicados, en los registros que cumplan cierta condición
DELETE Encargado de eliminar los registros de una tabla que
cumplan una condición
SELECT Encargado de consultar registros de la base de datos
que satisfagan una condición determinada

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Inserción de datos - INSERT

Podemos insertar valores en una tabla de grado n de dos formas:


Sin especificar los nombres de las columnas, sólo los valores:
INSERT INTO nombre_tabla
VALUES (v1 ,v2 ,..., vn )

Especificando el nombre de los k ≤ n atributos para los que


insertamos valores
INSERT INTO nombre_tabla (col1 , col2 , ..., colk )
VALUES (v1 , v2 , ..., vk )

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Inserción de datos - INSERT


Ejemplos

Suponiendo que los campos son codigo, nombre,


tipo, precio y procedencia, podemos hacer:
INSERT INTO productos
VALUES (1, 'Peras', 3, 0.75, 'Utrera');
o bien...
INSERT INTO productos (codigo, precio)
VALUES (5, 0.60);
En el segundo ejemplo, los valores no indicados explı́citamente
toman el valor NULL, o bien el valor por defecto si lo hemos
definido mediante DEFAULT.
Deben respetarse las restricciones establecidas (de entidad,
referencial, condición de requerido...)
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Modificadores

El uso de UPDATE, DELETE y SELECT necesita modificadores que


indiquen a qué tuplas afectan.
Ciertos modificadores (cláusulas) nos permiten generar criterios para
definir los datos a manipular o selecionar.
FROM: establece la tabla o tablas de la/s que seleccionar los registros
WHERE: condiciones que los registros a seleccionar deben cumplir
GROUP BY: criterio para agrupar los registros seleccionados
HAVING: establece condiciones sobre datos calculados para los
grupos generados por GROUP BY
ORDER BY: ordena los registros seleccionados según el orden
indicado

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Operadores lógicos

Estos operadores permiten formar condiciones más complejas a


partir de otras pasadas como operandos. Ası́, dadas tres
condiciones (expresiones lógicas) a, b y c:
a AND b: conjunción, evalúa las condiciones a y b y devuelve
verdad si ambas son ciertas.
a OR b: disyunción lógica, evalúa a y b y devuelve verdad si
alguna de las dos es cierta.
NOT c: negación lógica, devuelve el valor lógico contrario a la
evaluación de a.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Operadores de comparación

Para cada condición simple, antes de agruparlas mediante los


operadores lógicos anteriores, podemos emplear operadores como:
= Igual que, <> Distinto de
< Menor que, > Mayor que
<= Menor o igual que (>= Mayor o igual que)
x BETWEEN a AND b Devuelve los registros en los que el valor
de campo a esté entre a y b, ambos inclusive.
LIKE Utilizado en la comparación de un modelo
IN Utilizado para especificar registros de una base de datos

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Funciones de agregado

Las funciones de agregado se usan dentro de una cláusula SELECT


en grupos de registros (un grupo por cada combinación de valores
de GROUP BY, o un único grupo global si no hay GROUP BY) para
devolver un valor para cada posible grupo.
AVG calcula el promedio de valores de un campo determinado
COUNT devuelve el número de registros del grupo
SUM devuelve la suma de valores de un campo determinado
para el grupo
MAX devuelve el valor más alto de un campo especificado (MIN
el más bajo)

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Consultas de Selección

Las consultas de selección se utilizan para indicar al motor de


datos que devuelva información de las bases de datos. Esta
información es devuelta en forma de conjunto de registros que se
pueden almacenar en una nueva tabla.
SELECT Campos FROM Tabla;
Donde campos es la lista de campos que se deseen recuperar y
tabla es el origen de los mismos.
Por ejemplo,
SELECT Nombre, Telefono FROM Clientes;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Consultas de Selección

Se puede especificar el orden en que se desean recuperar los


registros de las tablas mediante la cláusula ORDER BY
SELECT CodigoPostal, Nombre, Telefono
FROM Clientes
ORDER BY Nombre;
Se puede indicar si el orden de los registros es ascendente, ASC
(valor por defecto) o descendente, DESC.
SELECT CodigoPostal, Nombre, Telefono
FROM Clientes
ORDER BY CodigoPostal DESC;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Consultas de Selección

En cuanto al conjunto de registros seleccionados, estos


modificadores, que se incluyen entre SELECT y el primer nombre
del campo a recuperar, provocan las siguientes acciones:
* Devuelve todos los campos de la tabla (valor por defecto)
LIMIT n Devuelve un determinado número de registros (n) de
la tabla.
DISTINCT Omite repeticiones de registros cuyos campos
seleccionados coincidan totalmente
DISTINCTROW Omite repeticiones de registros basándose en la
totalidad del registro y no sólo en los campos seleccionados.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Consultas de Selección
Ejemplos

SELECT * FROM Empleados;

SELECT Nombre, Apellido


FROM Estudiantes
ORDER BY Nota LIMIT 25;

SELECT DISTINCT Apellido


FROM Empleados;

SELECT DISTINCTROW Apellido


FROM Empleados;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Alias (AS)

En determinadas circunstancias es necesario asignar un


nombre nuevo a alguna columna determinada de un conjunto
de registros devuelto por una consulta.
Usamos la palabra reservada AS, que se encarga de asignar el
nombre que deseamos a la columna deseada.
Por ejemplo,
SELECT DISTINCTROW Apellido AS Empleado
FROM Empleados;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Estableciendo condciones para la consulta

Operadores lógicos
SELECT *
FROM Empleados
WHERE (Sueldo > 100 AND Sueldo < 500) OR
(Provincia='Madrid' AND Estado='Casado');
Operador BETWEEN:
SELECT *
FROM Pedidos
WHERE CodPostal BETWEEN 28000 AND 28999;
Combinado con NOT:
SELECT *
FROM Pedidos
WHERE cp NOT BETWEEN 28000 AND 28999;
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Operador LIKE

Permite comparar una cadena con un patrón. Su sintaxis es:


expresión LIKE modelo,
y admite comodines (algunos dependen del SGBD):
(guión bajo) sirve para cualquier carácter unitario
% comodı́n para cero o más caracteres
Una clase [...] puede tomar cualquier valor entre los
corchetes. Por ejemplo, [abc] indica que en esa posición
pueden ir a, b o c. Para un rango de valores, usamos el guión
medio: [a-z] indica cualquier letra y [0-9] dı́gito.
ˆ acepta cualquier carácter menos los indicados. Por ejemplo,
[ˆoa] acepta cualquier carácter menos o y a.
Como vemos en este enlace, Access emplea sı́mbolos distintos.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Operador IN

Este operador devuelve los registros cuyo campo indicado coincide


con alguno de los dados en una lista. Su sintaxis es:
expresión [NOT] IN (valor1, valor2, ...)
Por ejemplo:
SELECT *
FROM Pedidos
WHERE Provincia IN ('Madrid', 'Cádiz', 'Sevilla');

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Cuantificador EXISTS

El cuantificador existencial en SQL es EXISTS. La expresión serı́a:

WHERE EXISTS (SELECT ... FROM ...)

Esta condición se cumple (es verdadera) si, y sólo si, el resultado


de evaluar la consulta especificada por

SELECT ... FROM ...

devuelve algún registro (i.e., no es el conjunto vacı́o). Esta


expresión interna al paréntesis se denomina subconsulta.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Ejemplos con WHERE

SELECT Apellidos, Salario SELECT Apellidos, Nombre


FROM Empleados FROM Empleados
WHERE Salario > 21000; WHERE Apellidos Like 'S%';

SELECT Apellidos, Nombre SELECT Apellidos, Salario


FROM Empleados FROM Empleados
WHERE Apellidos = 'King'; WHERE Salario Between 200 and 300;

SELECT Apellidos, Nombre, Ciudad


FROM Empleados
WHERE Ciudad IN ('Sevilla', 'Los Ángeles', 'Barcelona')
OR Nombre NOT LIKE '%B%';

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Agrupamiento - GROUP BY
GROUP BY lista campos
combina los registros con valores idénticos para lista campos en un
grupo, para el que se mostrará un único registro. Si se incluye una
función SQL agregada (Sum, Count...) en el SELECT, se obtiene
un valor del cálculo para cada registro (grupo). Su sintaxis es:
SELECT expresiones
FROM tabla
[WHERE lista criterios]
GROUP BY lista campos;
Por ejemplo:
SELECT Id_Familia, Sum(Stock)
FROM Productos
GROUP BY Id_Familia;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Agrupamiento - HAVING
Una vez GROUP BY ha combinado los
registros, HAVING filtra los registros
agrupados que satisfagan las
condiciones del HAVING.
Es similar a WHERE, determina qué
registros se seleccionan. Pero a
diferencia de éste (que afecta a los SELECT Id_Familia, SUM(Stock)
registros originales), HAVING filtra los FROM Productos
registros resultantes de la agrupación, WHERE NombreProducto Like 'BOS%'
según los resultados de los campos GROUP BY Id_Familia
calculados. HAVING SUM(Stock) > 100
Es decir, una vez se han agrupado los
registros utilizando GROUP BY y se han
hecho los cálculos agregados, HAVING
determina cuáles de los nuevos
registros se van a mostrar.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Agrupamiento - AVG

Calcula, para cada grupo, la media aritmética de los valores del


campo especificado para los distintos registros del grupo. Su
sintaxis es AVG(expr), con expr siendo el campo (o expresión
derivada de campos) que contiene los datos numéricos a los que
calcular la media.

SELECT AVG(Gastos) AS Promedio


FROM Pedidos
WHERE Gastos > 100;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Agrupamiento - Count

Calcula el número de registros devueltos por una consulta,


para cada grupo.
Su sintaxis es: Count(expr), con expr el nombre del campo
que desea contar.
Los operandos de expr pueden incluir el nombre de un campo
(del tipo que sea, incluyendo texto), una constante o una
función
No cuenta los registros que tienen campos NULL, a menos que
expr sea el carácter *:
SELECT Count(*) AS Total
FROM Pedidos;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

COUNT
Algunos ejemplos adicionales

Con COUNT podemos contar el número de ocurrencias de cierto


campo (valores no nulos). Por ejemplo, para contar el número de
empleados con la ciudad informada:
SELECT COUNT(ciudad)
FROM EMPLEADOS
Ahora bien, si queremos saber el número de ciudades (sin
repeticiones), incluimos DISTINCT:
SELECT COUNT(DISTINCT ciudad)
FROM EMPLEADOS

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Agrupamiento - Max, Min

Min(expr) y Max(expr) devuelven, respectivamente, el mı́nimo o


el máximo de un conjunto de valores contenidos en un campo de
una consulta. Ası́, expr es el campo o expresión (incluyendo
constantes, llamadas a funciones, etc.) sobre el que realizar el
cálculo.

SELECT Min(gasto) AS gmin SELECT Max(gasto) AS gmax


FROM Pedidos FROM Pedidos
WHERE pais = 'España'; WHERE pais = 'España';

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Agrupamiento - Sum

Sum(expr) devuelve la suma de valores para el campo o expresión


especificada. Los operandos de expr pueden incluir nombres de
campos de tablas, constantes, llamadas a funciones y operadores.

SELECT Sum(PrecioUnidad * Cantidad) AS Total


FROM DetallePedido;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Producto cartesiano

El producto cartesiano entre dos relaciones (tablas) se realiza, en su


forma más elemental, mediante la separación por comas. Ası́, sea:
T1 con 3 columnas y 5 filas.
T2 con 4 columnas y 7 filas.
Podemos devolver el producto cartesiano mediante:
SELECT *
FROM T1, T2;
y éste resultado tendrá 7 (=3+4) columnas y 35 (=5 * 7) filas.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Joins

En general, denominamos JOIN al producto cartesiano filtrado por


ciertas condiciones que restrinjan el resultado a los registros que
cumplan ciertas condiciones (usando valores de ciertas columnas
de las tablas involucradas). Si hay campos con el mismo nombre,
los prefijamos.
SELECT * FROM TABLA1, TABLA2
WHERE TABLA1.ID=7 AND TABLA2.ID=9;
Podemos usar alias para no tener que escribir el nombre completo
de la tabla:
SELECT * FROM TABLA1 a, TABLA2 b
WHERE a.ID=7 AND b.ID=9;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Joins

Podemos incluir restricciones de igualdad que afecten a columnas


de distintas tablas.
SELECT * FROM TABLA1, TABLA2
WHERE TABLA1.ID=TABLA2.ID;
Para evitar la columna ID duplicada, lo más común es usar
INNER JOIN, con ON:
SELECT a.NOMBRE, b.DEPTO
FROM TABLA1 a INNER JOIN TABLA2 b ON a.ID=b.ID;
o bien USING5 :
SELECT a.NOMBRE, b.DEPTO
FROM TABLA1 a INNER JOIN TABLA2 b USING(ID);
5
En según que SGBD y versión, también podremos indicar NATURAL JOIN, y
omitir USING: SELECT T1.NOMB, T2.DEPT FROM T1 NATURAL JOIN T2
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Joins
Reflexividad

Para hacer JOIN a la propia tabla, lo más común es renombrar dos


veces la tabla:

SELECT a.NOMBRE, b.NOMBRE


FROM EMPLEADOS a INNER JOIN EMPLEADOS b
ON a.ID = b.ID_SUPERVISOR;

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Subconsultas

Podemos tener una consulta contenida dentro de otra. Tiene


carácter temporal y se resuelve antes de la consulta principal.
SELECT producto, precio
FROM tabla
WHERE precio = (SELECT MAX(precio) FROM tabla);

SELECT producto, precio


FROM tabla
WHERE precio <> (SELECT MAX(precio) FROM tabla);

SELECT producto, precio


FROM tabla
WHERE producto NOT IN (SELECT producto FROM tabla2);

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

CASE - Primer uso


Formato general:
CASE
WHEN cond1 THEN expr1
[WHEN cond2 THEN expr2]
[ELSE expr3]
END
Ejemplo:
SELECT Nombre, CASE WHEN Turno = 'Mañana' THEN 1
ELSE 2 END as Turno
FROM Alumnos;
Devuelve el campo ’Nombre’, y una segunda columna ’Nivel’
formada a partir de la Columna ’Turno’ sustituyendo el valor
’Mañana’ por 1 y cualquier otro valor por 2.
Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos
Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

ANY

Formato general:
Operador ANY Subconsulta
ANY se usa con un operador de comparación, y el resultado de la
misma se evalúa como Verdadero si la comparación resulta cierta
para algún valor devuelto por la subconsulta.

Por ejemplo:
SELECT s1
FROM t1
WHERE s1 > ANY (SELECT s1 FROM t2);

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

COALESCE

Devuelve el primer valor conocido (no NULL) de una lista.

SELECT Nombre,
COALESCE(FijoCasa, FijoTrabajo, Móvil) Telefono
FROM Clientes;

Devuelve el nombre y un teléfono de cada cliente: si se conoce, el


fijo de casa; si no el fijo del trabajo y si no el móvil, en ese orden.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Creación de Tablas a partir de consultas

Podemos crear tablas a partir de subconsultas:


CREATE TABLE TABLA1 [AS]
SELECT Titulo, Autor
FROM Libros;

Se guarda ası́ la nueva tabla, incluyendo su esquema y datos.

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Índice

1 Introducción
2 Data Definition Language
3 Data Manipulation Language
4 Select
5 Group by
6 Joins
7 Otros
8 Bibliografı́a

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Bibliografı́a I

Mercedes Marqués
Apuntes de Bases de Datos.
Universidad Jaume I en Castellón (2011)
ISBN: 978-84-693-0146-3

Carme Martı́n Escofet


El lenguaje SQL.
UOC (2007)
P06/M2109/02149
Alan Beaulieu
Aprende SQL.
Anaya Multimedia - O’Reilly, Segunda Ed. (2009)
ISBN: 978-84-4152-637-2

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Bibliografı́a II

Luis Grau Fernandez, Ignacio López Rodrı́guez


Problemas de Bases de Datos.
Sanz Y Torres, S.L. - 3ª Edición (2006)
ISBN: 978-84-960-9469-7

Dolores Cuadra, Elena Castro, Ana Mª Iglesias, Paloma Martı́nez,


Fco. Javier Calle, César de Pablo, Harith Al-Jumaily, Lourdes
Moreno, Sonia Garcı́a Manzano, José Luis Martı́nez, Jesica Rivero,
Isabel Segura
Desarrollo De Bases De Datos: Casos Prácticos Desde El Análisis A
La Implementación.
RA-MA Editorial - 2ª Edición (2013)
ISBN: 978-84-996-4124-9

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Introducción DDL DML Select Group by Joins Otros Biblio

Bibliografı́a III

Adoracion De Miguel Castaño, Paloma Martı́nez Fernández, Elena


Castro Galán
Diseño De Bases De Datos: Problemas resueltos.
RA-MA Editorial - 1ª Edición (2001)
ISBN: 978-97-015-0687-5

SQL Zoo - https://sqlzoo.net/

SQL Tutorial - https://www.w3schools.com/sql

SQLite Online - https://sqliteonline.com/

SQLite Fiddle - http://sqlfiddle.com/

Luis Valencia Cabrera (lvalencia@us.es) Bases de Datos


Introducción a SQL
Consultas SQL (SELECT)

Consultas sencillas
Devolver todos los campos de una tabla (SELECT *)

SELECT *
FROM CLIENTES
Con el * indicamos que queremos devolver todos los campos. Si CLIENTES dispone de los
campos idCliente, nombre y descripcion, lo anterior sería equivalente a:

SELECT idCliente, nombre, descripcion


FROM CLIENTES
Obviamente, al querer todos los campos, esto es innecesario y es por tanto más conveniente
emplear el asterisco (*). También sería equivalente emplear la notación completa:

SELECT CLIENTES.idCliente, CLIENTES.nombre, CLIENTES.descripcion


FROM CLIENTES
Al tener únicamente una tabla involucrada, podemos referirnos a los campos sin calificar, dado
que no hay duda de a qué tabla se refiere. Cuando veamos consultas sobre varias tablas
comprenderemos la necesidad de incluir esta notación calificada (TABLA.campo).

Devolver un subconjunto de los campos de una tabla (SELECT DISTINCT)

SELECT cp, ciudad


FROM DIRECCION
Esta consulta devolverá únicamente los campos cp (código postal) y ciudad de la tabla
DIRECCION. Al tener un subconjunto de los campos, éstos no tienen por qué incluir a la clave
de la tabla, por lo que no tienen por qué ser únicos. Así, si tenemos muchos registros referidos
a distintas calles y números de ese mismo código postal y ciudad, nos encontraremos muchos
registros repetidos. Esto puede evitarse haciendo:

SELECT DISTINCT cp, ciudad


FROM CLIENTES
Así se eliminan los registros repetidos, devolviendo únicamente una vez cada par cp, ciudad.
Esta selección de un subconjunto de los datos de la tabla y excluyendo repetidos se denomina
en álgebra relacional proyección.

Devolver un subconjunto de los registros de una tabla (WHERE)

SELECT numero, calle


FROM DIRECCION
WHERE ciudad = ‘Sevilla’
Esta consulta devolvería el número y la dirección de todas las direcciones pertenecientes a la
ciudad de Sevilla. Como vemos, con WHERE indicamos la condición que deben cumplir los
registros de la tabla para ser devueltos en la consulta. En este caso tenemos una condición
simple dada por la comparación de igualdad (=) entre al campo (ciudad) y un literal de tipo
cadena, entre comillas simples (‘Sevilla’).
SELECT calle, ciudad
FROM DIRECCION
WHERE numero = 12
Esta otra consulta devolvería la calle y ciudad de todos los registros de la tabla con el número
12, en este caso un literal numérico. Las condiciones empleadas pueden ser mucho más
complejas incluyendo otro tipo de operadores y combinaciones de los mismos.

Operadores relacionales
Al margen del signo de igualdad empleado anteriormente, se pueden usar n las condiciones
simples de las consultas los operadores relacionales habituales, devolviendo siempre un valor
booleano (lógico):

Operador Significado
< Menor que
> Mayor que
<> Distinto de
<= Menor ó Igual que
>= Mayor ó Igual que
= Igual que

SELECT nombre
FROM CLIENTES
WHERE edad <= 32

Adicionalmente, disponemos de operadores de comparación adicionales, también devolviendo


valores booleanos (lógicos) True o False según si se cumplen o no las condiciones:

BETWEEN: para indicar un intervalo de valores.


SELECT nombre
FROM CLIENTES
WHERE edad BETWEEN 20 AND 35

LIKE: empleado para comparar patrones de texto pudiendo incluir comodines como los
siguientes:
Comodín Descripción
% Sustituto para cero o más caracteres.
_ Sustituto para exactamente un carácter
[lista caracteres] Cualquier carácter de la lista
[^lista caracteres] Cualquier carácter que no esté en la lista
[!lista caracteres] Cualquier carácter que no esté en la lista

SELECT num, calle, cp


FROM DIRECCION
WHERE ciudad LIKE ‘Val%’
Esta consulta devolvería los datos de las direcciones de toda ciudad que comience por Val y
siga por cualquier número de caracteres, incluyendo cero caracteres. Por ejemplo, Valladolid o
Valencia. En el enlace anterior sobre patrones de texto podemos practicar directamente desde
la web.

IN: empleado para comparar con una lista de valores fijados de modo que devuelva True si el
campo indicado pertenece a la lista.
SELECT num, calle, direccion
FROM DIRECCION
WHERE ciudad IN (‘Sevilla’, ’Córdoba’, ‘Huelva’, ‘Cádiz’)

Operadores lógicos (AND, OR, NOT)


Los operadores lógicos nos sirven para componer expresiones de filtrado a partir de las
anteriores:

Operador Significado
AND Y lógico
OR O lógico
NOT Negación lógica

La precedencia y asociatividad es la habitual definida en la Lógica. En cualquier caso, cuando


incluya expresiones que empleen varios de estos operadores es recomendable usar paréntesis
para evitar errores. Por ejemplo:

SELECT *
FROM DIRECCION
WHERE ciudad = ‘Sevilla’ AND cp = 41009 OR ciudad = ‘Córdoba’ AND NOT cp = 14010
Devuelve los registros pertenecientes a direcciones que tengan el código postal 41009 de
Sevilla o bien que no tengan el 14010 de Córdoba. La mayor precedencia la adopta el operador
NOT sobre la condición cp = 14010; a continuación los AND se aplican sobre ciudad = ‘Sevilla’
AND cp = 41009 y ciudad = ‘Córdoba’ AND NOT cp = 14010; por último se aplica el OR sobre la
fórmula completa. La misma consulta se puede expresar de forma más clara con paréntesis:
SELECT *
FROM DIRECCION
WHERE (ciudad = ‘Sevilla’ AND cp = 41009) OR
(ciudad = ‘Córdoba’ AND (NOT cp = 14010))
O bien si el NOT nos parece más evidente, podemos excluir el paréntesis interior, a nuestra
gusto siempre conservando el significado que queríamos dar la operación.

Ordenación
Ordenar según criterios (ORDER BY)
Podemos ordenar los registros devueltos por una consulta por el campo o campos que
estimemos oportunos:

SELECT *
FROM CIUDAD
ORDER BY provincia ASC, numhabitantes DESC
Esta consulta devolvería todas las ciudades ordenadas por provincia en orden ascendente, y
dentro de los de la misma provincia ordenaría las ciudades por orden descendente del número
de habitantes. Si no indicamos ASC ni DESC, el comportamiento por defecto será el orden
ascendente (ASC).

Devolución de expresiones
Asignación de un alias a un dato devuelto (AS)
SELECT idCliente AS id, nombre AS cliente, descripcion AS desc
FROM CLIENTES

Uso de expresiones empleando operadores y/o funciones


Podemos practicar en SQLzoo a usar expresiones con operadores y funciones. Por ejemplo:

SELECT MOD(DAY(NOW()),7) AS numSemana, POW(2,3) AS potencia8


Devuelve el número de semana en la que nos encontramos dentro del mes, ya que NOW() nos
devuelve la fecha/hora actual, de la cual extraemos el día con DAY, y posteriormente
calculamos el módulo 7 de dicho día (de modo que para un día 26 devolvería un 5, por
ejemplo). El dato con alias potencia8 devolvería 8 (2 elevado a 3, POW es power, potencia).

Se puede combinar naturalmente la potencia de este lenguaje de expresiones usando


operadores y funciones sobre los datos de los registros de una tabla:
SELECT DAY(fechaLinea) AS dia, FLOOR(precioLinea * 0.85) AS precioDtoRedondeado
FROM LINEAPEDIDO

Consultas agrupadas (GROUP BY)


Las consultas anteriores recuperaban, trabajaban con, y mostraban información a nivel de
cada registro individual de la base de datos. Así, si tenemos un producto con un determinado
precio, podemos devolver el precio mediante SELECT precioLinea o bien operar sobre él como
en SELECT precioLinea * 0.85.

Ahora bien, podemos querer obtener información que no proviene de un registro individual
sino de la agrupación de información, como es el caso de contar el número de líneas de
pedido, sumar el precio de todas las líneas por cada pedido, etc. Para ello, debemos emplear
funciones agregadas y en la mayoría de los casos agrupar por algún campo.

Así, para ver el número total de registros podemos hacer:


SELECT COUNT(*)
FROM LINEAPEDIDO

Si por el contrario deseamos obtener el total de líneas por pedido, debemos indicar que
agrupe por idPedido, lo que contará todos los registros con el mismo idPedido y calculará su
cuenta:
SELECT idPedido, COUNT(*)
FROM LINEAPEDIDO
GROUP BY idPedido

Lo mismo se puede aplicar a otras funciones como la suma, indicando en ese caso aparte de la
agrupación el campo que queremos sumar:
SELECT idPedido, SUM(precioLinea)
FROM LINEAPEDIDO
GROUP BY idPedido
¿Y si queremos hallar la media de los precios por cada pedido? En ese caso necesitamos de
nuevo agrupar (GROUP BY) por pedido.
SELECT idPedido, AVG(precioLinea)
FROM LINEAPEDIDO
GROUP BY idPedido

Igualmente, podríamos aplicar un redondeo (ROUND) sobre la media, para dejar 4 decimales, y
aplicarle un alias (AS) para el nombre del dato de salida.
SELECT idPedido, ROUND(AVG(precioLinea),4) AS media
FROM LINEAPEDIDO
GROUP BY idPedido

O podríamos establecer una condición sobre el dato agrupado (HAVING), de forma que
solamente se muestren las medias menores o iguales que 10. Existe una gran cantidad de
funciones de agregación definidas en SQL, pero hay que tener precaución porque pueden
diferir de un SGBD a otro.

SELECT idPedido, ROUND(AVG(precioLinea),4)


FROM LINEAPEDIDO
GROUP BY idPedido
HAVING AVG(precioLinea) < 10

Para practicar un poco con las más comunes es muy recomendable este tutorial interactivo. En
MySQL tendríamos las que aparecen en este enlace. Este es el desglose completo de las
funciones de agregación estándar:

Function Usage
Computes the average value of a column given
AVG(expression)
by expression.

CORR(dependent, independent) Computes a correlation coefficient.

COUNT(expression) Counts the rows defined by the expression.


COUNT(*) Counts all rows in the specified table or view.

COVAR_POP (dependent, independent) Computes population covariance.

COVAR_SAMP(dependent, independent) Computes sample covariance.

Computes the relative rank of a hypothetical


row within a group of rows, where the rank is
CUME_DIST(value_list) WITHIN GROUP
equal to the number of rows less than or equal
(ORDER BY sort_list)
to the hypothetical row divided by the number
of rows in the group.
Generates a dense rank (no ranks are skipped)
DENSE_RANK(value_list) WITHIN GROUP
for a hypothetical row (value_list) in a group of
(ORDER BY sort_list)
rows generated by GROUP BY.
Finds the minimum value in a column given by
MIN(expression)
expression.
Finds the maximum value in a column given by
MAX(expression)
expression.
Generates a relative rank for a hypothetical row
PERCENT_RANK(value_list) WITHIN GROUP
by dividing that row's rank less 1 by the number
(ORDER BY sort_list)
of rows in the group.
Generates an interpolated value that, if added
PERCENTILE_CONT (percentile) WITHIN
to the group, would correspond to the
GROUP (ORDER BY sort_list)
percentile given.
Returns the value with the smallest cumulative
PERCENTILE_DISC (percentile) WITHIN
distribution value greater than or equal to
GROUP (ORDER BY sort_list)
percentile.
Generates a rank for a hypothetical row
RANK(value_list) WITHIN GROUP (ORDER
(value_list) in a group of rows generated by
BY sort_list)
GROUP BY.
Computes the average of the independent
REGR_AVGX(dependent, independent)
variable.
Computes the average of the dependent
REGR_AVGY(dependent, independent)
variable.
Counts the number of pairs remaining in the
REGR_COUNT(dependent, independent) group after any pair with one or more NULL
values has been eliminated.
Computes the y-intercept of the least-squares-
REGR_INTERCEPT(dependent,independent)
fit linear equation.

REGR_R2(dependent, independent) Squares the correlation coefficient.

Determines the slope of the least-squares-fit


REGR_SLOPE(dependent, independent)
linear equation.

REGR_SXX(dependent, independent) Sums the squares of the independent variables.

REGR_SXY(dependent, independent) Sums the products of each pair of variables.

REGR_SYY(dependent, independent) Sums the squares of the dependent variables.

Computes the population standard deviation of


STDDEV_POP(expression)
all expression values in a group.
Computes the sample standard deviation of all
STDDEV_SAMP(expression)
expression values in a group.
Computes the sum of column values given by
SUM(expression)
expression.
Computes the population variance of all
VAR_POP(expression)
expression values in a group.
Computes the sample standard deviation of all
VAR_SAMP(expression)
expression values in a group.
Devolución de filas nulas/no nulas (IS NULL / IS NOT NULL)
SELECT idPedido
FROM PEDIDO
WHERE direccionEnvio IS NULL
Devolvería los pedidos que no tienen dirección de envío asociada.

Consultas por intersecciones entre tablas (JOIN)


Podemos generar una consulta que obtenga datos de varias tablas, pudiendo establecer a su
vez criterios sobre otras. Veamos los tipos fundamentales (una buena explicación se puede
encontrar aquí). Por ejemplo, dados los clientes de nuestro concesionario y nuestras ventas de
coches a clientes en los diversos concesionarios,

VENTA

CLIENTE

podemos obtener una consulta que obtenga datos del cliente y de la venta. Por ejemplo,
nombre, apellidos, codcoche y color, mediante una consulta del tipo:

SELECT nombre, apellidos, codcoche, color


FROM CLIENTE, VENTA
WHERE CLIENTE.cifcl = VENTA.idCliente

INNER JOIN

INNER JOIN implícito


Por ejemplo, para obtener los datos del cliente y el pedido en la misma consulta:
SELECT nombreCliente, idPedido, fechaPedido
FROM CLIENTE, PEDIDO
WHERE CLIENTE.idCliente = PEDIDOpedido.idCliente
Como vemos, podemos empezar escribiendo tal cuál qué datos nos piden (SELECT), de dónde
podemos obtenerlos (FROM) y qué criterio (WHERE). Esta es la versión más antigua de SQL,
aunque se sigue empleando, conociéndose como JOIN implícito ya que no se usa por ningún
lado la palabra JOIN, pero se está haciendo la intersección por la foreign key, en este caso la
columna idCliente.
Si omitimos en el caso anterior el WHERE:
SELECT nombreCliente, idPedido, fechaPedido
FROM CLIENTE, PEDIDO
Obtendremos los datos solicitados para todos los pares de registros de CLIENTE y PEDIDO, el
producto cartesiano, de forma que si hay 3 registros en CLIENTE y 4 en PEDIDO devolveremos
12 registros. Puede probar estos comportamientos en este enlace. La explicación detallada de
un ejemplo similar con coches y marcas se puede encontrar en esta entrada de blog. Este tipo
de join se conoce como CROSS JOIN, y en este caso se ha hecho de forma implícita.

INNER JOIN natural (NATURAL JOIN)


SELECT nombreCliente, idPedido, fechaPedido
FROM CLIENTE NATURAL JOIN PEDIDO
Esta consulta obtiene lo mismo que el join implícito inicial, de forma que NATURAL JOIN
establece la condición de igualdad entre los campos con el mismo nombre.

INNER JOIN explícito


La forma más habitual de INNER JOIN es la que intersecta las tablas indicadas en con INNER
JOIN por el campo indicado por ON.
SELECT nombreCliente, idPedido, fechaPedido
FROM CLIENTE INNER JOIN PEDIDO
ON cliente.idCliente = pedido.idCliente
Este comportamiento se explica y puede probar aquí, en este otro enlace o finalmente aquí.
Como vemos, es equivalente al INNER JOIN implícito, pero en lugar de establecer una
condición sobre los campos de las relaciones en el WHERE, establece la condición asociada a la
relación entre ambas tablas a través de la FOREIGN KEY, en este caso desde el atributo
(campo) idCliente en la relación (tabla) PEDIDO, FOREIGN KEY que hace referencia al atributo
idCliente de la relación CLIENTE.

Con la notación explícita también podemos expresar un CROSS JOIN como se indicó en el caso
explícito:

SELECT nombreCliente, idPedido, fechaPedido


FROM CLIENTE CROSS JOIN PEDIDO

Nota: aunque lo más frecuente es que la condición del JOIN sea en términos de igualdad entre
las claves, también se podrían establecer condiciones empleando otros operadores
relacionales (operadores para comparar dos valores, devolviendo un resultado booleano, es
decir, cierto o falso):

SELECT nombreCliente, idPedido, fechaPedido


FROM CLIENTE INNER JOIN PEDIDO
ON cliente.idCliente < pedido.idCliente
LEFT JOIN

El resultado de esta operación siempre contiene todos los registros de la relación izquierda
(primera tabla que indicamos), y aquellos de la tabla derecha que cumplen la condición
establecida. Para el resto aparecerá en los campos correspondientes a dicha tabla un NULL.
SELECT nombreCliente, idPedido, fechaPedido
FROM CLIENTE LEFT JOIN PEDIDO
ON cliente.idCliente = pedido.idCliente
Esta consulta devolverá todos los clientes con sus pedidos, y un registro por cada cliente que
no tenga pedidos.

RIGHT JOIN

El RIGHT JOIN es análogo al LEFT JOIN, pero devolviendo todos los registros de la relación
derecha (segunda tabla que aparece), y únicamente aquellos de la tabla izquierda que cumplen
la condición del JOIN. El resultado de esta operación siempre contiene todos los registros de la
relación derecha (segunda tabla que indicamos), de modo que en aquellos sin equivalente en
la parte izquierda tendrán en los campos correspondientes a dicha tabla un NULL.
SELECT nombreCliente, idPedido, fechaPedido
FROM CLIENTE RIGHT JOIN PEDIDO
ON cliente.idCliente = pedido.idCliente
Asumiendo que pudiéramos tener en la base de datos pedidos sin cliente asociado, esta
consulta devolverá todos los pedidos con sus clientes, y en caso de que el cliente no aparezca
el nombreCliente sería NULL.

FULL OUTER JOIN

SELECT EMPLEADO.nombre, EMPLEADO.apellidos, EMPRESA.nombre


FROM EMPLEADO FULL OUTER JOIN EMPRESA
ON EMPLEADO.empresa = EMPRESA.cif
Esta consulta devolvería tanto los datos de las empresas sin empleados como los de los
empleados sin empresa, apareciendo rellenos todos los datos de la consulta únicamente para
aquellos registros que cumplen la condición del JOIN, y apareciendo NULL en unos u otros
campos para el resto de registros.

Como se puede ver, esta consulta es equivalente a mostrar tanto los registros devueltos por el
LEFT como por el RIGHT JOIN, eliminando los repetidos (aquellos registros que cumplan la
condición del JOIN, que serían devueltos por ambas consultas).
El hecho de unir los registros de las consultas de LEFT y JOIN, ambas devolviendo los mismos
tipos de campos (EMPLEADO.nombre, EMPLEADO.apellidos, EMPRESA.nombre) puede ser
expresado en SQL a través de la cláusula UNION:

SELECT EMPLEADO.nombre, EMPLEADO.apellidos, EMPRESA.nombre


FROM EMPLEADO
LEFT JOIN EMPRESA
ON EMPLEADO.empresa = EMPRESA.cif
UNION
SELECT EMPLEADO.nombre, EMPLEADO.apellidos, EMPRESA.nombre
FROM EMPLEADO
RIGHT JOIN EMPRESA
ON EMPLEADO.empresa = EMPRESA.cif

Para devolver los registros de la consulta anterior excluyendo los repetidos haríamos:

SELECT DISTINCTROW
FROM (SELECT EMPLEADO.nombre, EMPLEADO.apellidos, EMPRESA.nombre
FROM EMPLEADO
LEFT JOIN EMPRESA
ON EMPLEADO.empresa = EMPRESA.cif
UNION
SELECT EMPLEADO.nombre, EMPLEADO.apellidos, EMPRESA.nombre
FROM EMPLEADO
RIGHT JOIN EMPRESA
ON EMPLEADO.empresa = EMPRESA.cif)

Ahora bien, podríamos haber evitado los duplicados mediante una solución más ingeniosa,
devolviendo en una de las dos consultas (LEFT o RIGHT) solamente los registros de una de las
partes, excluyendo así los que cumplen la condición del JOIN, que serán devueltos por la otra:

SELECT EMPLEADO.nombre, EMPLEADO.apellidos, EMPRESA.nombre


FROM EMPLEADO
LEFT JOIN EMPRESA
ON EMPLEADO.empresa = EMPRESA.cif
UNION
SELECT EMPLEADO.nombre, EMPLEADO.apellidos, EMPRESA.nombre
FROM EMPLEADO
RIGHT JOIN EMPRESA
ON EMPLEADO.empresa = EMPRESA.cif
WHERE EMPLEADO.empresa IS NULL

Algunos ejercicios adicionales sobre JOIN pueden encontrarse en este tutorial y los primeros 4
apartados de este otro (los restantes ejercicios emplean conceptos que no hemos visto),
ambos en SQLZOO.
Consultas anidadas
A veces se han de utilizar en una consulta los resultados de otra consulta, llamada subconsulta
o consulta anidada. Podemos ver muchos ejemplos de ello aquí. Veamos que existen diversas
variantes:

Empleando IN
Obtener el identificador de los clientes que han comprado algún coche a un concesionario de
Madrid.
SELECT DISTINCT cifcl
FROM VENTA
WHERE cifc IN (SELECT cifc
FROM CONCESIONARIO
WHERE ciudad = 'Madrid')

Obtener el código de coche de los coches vendidos por algún concesionario de Madrid.
SELECT DISTINCT codcoche
FROM VENTA
WHERE cifc IN (SELECT cifc
FROM CONCESIONARIO
WHERE ciudad = 'Madrid')

Obtener el nombre y el modelo de los coches vendidos por algún concesionario de Barcelona.
SELECT nombre, modelo
FROM COCHE
WHERE codcoche IN (SELECT codcoche
FROM VENTA
WHERE cifc IN (SELECT cifc
FROM CONCESIONARIO
WHERE ciudad = 'Barcelona'))

Empleando operadores relacionales


Un ejemplo típico sería conocer los nombres de los empleados cuyo salario está por encima de
la media:
SELECT nombre
FROM EMPLEADOS
WHERE salario > (select avg(salario) from emp);
Obtener el nombre y apellidos de los clientes cuyo identificador de cliente es menor que el de
Juan Martín.

SELECT nombre, apellidos


FROM CLIENTE
WHERE cifcl < (SELECT cifcl
FROM CLIENTE
WHERE nombre = 'Juan'
AND apellido = 'Martín')
Empleando ALL
Obtener el nombre y apellidos de los clientes cuyo identificador de cliente es menor que el de
los de Barcelona.

SELECT nombre, apellidos


FROM CLIENTE
WHERE cifcl < ALL (SELECT cifcl
FROM CLIENTE
WHERE ciudad = 'Barcelona')

Empleando ANY
Obtener el nombre y apellidos de los clientes cuyo identificador de cliente es mayor que el de
alguno de los de Madrid, y cuyo nombre empieza por a.
SELECT nombre, apellidos
FROM CLIENTE
WHERE cifcl > ANY
(SELECT cifcl
FROM CLIENTE
WHERE ciudad = 'Madrid')
AND nombre LIKE 'A%'

Empleando EXISTS

Obtener los identificadores de los clientes que sólo han comprado coches al concesionario 1.
SELECT cifcl
FROM VENTA va
WHERE NOT EXISTS (SELECT *
FROM VENTA vb
WHERE cifc <> 1
AND va.cifcl = vb.cifcl)

Obtener los identificadores de los clientes que han comprado coches al concesionario 1 y a
algún otro.
SELECT cifcl
FROM VENTA va
WHERE cifc = 1
AND EXISTS (SELECT *
FROM VENTA vb
WHERE cifc <> 1
AND va.cifcl = vb.cifcl)
Resumen sentencias SQL
Lenguaje de definición de datos (DDL):
Definición de tablas relacionales (CREATE TABLE): CREATE TABLE nombre_tabla (
atributo_1 dominio_1 [NOT NULL] [UNIQUE] [PRIMARY KEY] [DEFAULT valor],
..., atributo_n dominio_n [NOT NULL] [UNIQUE] [PRIMARY KEY]
[DEFAULT valor],
[PRIMARY KEY (atributo, ...)],
[FOREIGN KEY (atributodemitabla_i,...,atributomitabla_j)
REFERENCES otra_tabla (atributootratabla_i,...atributo_otratabla_j)]*
)

Eliminación de tablas (DROP TABLE):


CREATE [UNIQUE] INDEX nombre_indice ON nombre_tabla (nombre_atributo)

Eliminación de tablas (DROP TABLE):


DROP TABLE nombre_tabla

Moficiación de la definición de tablas (ALTER TABLE):


ALTER TABLE nombre_tabla acción
Siendo acción una de las siguientes:
• RENAME TO nuevo_nombre
• ADD [COLUMN] nombre_atributo definición_atributo
• DROP [COLUMN] nombre_atributo
• MODIFY nombre_atributo definición_atributo
• CHANGE nombre_atributo nuevo_nombre nueva_definición
• ALTER COLUMN nombre_atributo nuevo_nombre nueva_definición

Nota: MODIFY/CHANGE/ALTER COLUMN en MySQL/Oracle, ALTER COLUMN en SQL


Server/Access/PostgreSQL. El subconjunto más reducido lo encontramos en SQLite.

Tipos de datos
Pese a la pretensión de SQL como estándar, que define una serie de tipos, que podemos
encontrar en diversos recursos: W3Schools, SQL for dummies, etc. La realidad es que
dependiendo del SGBD que empleemos se dan cambios sustanciales: SQLite, Access, MySQL,
SQL Server, PostgreSQL, Oracle, etc. Por ejemplo, en SQLite solemos almacenar las fechas
como TEXT, de modo que trabajemos con ellas con instrucciones del tipo:

• CREATE TABLE T (ts TEXT)


• INSERT INTO T VALUES ('12/05/2010 15:54:32');
• SELECT * FROM T WHERE ts BETWEEN '12/05/2010 00:00:00' AND
'12/05/2010 23:59:59';
Lenguaje de manipulación de datos (DML):
Inserción de registros/filas en tablas (INSERT):
INSERT INTO nombre_tabla [(atributo_1,...,atributo_m)]
VALUES [(valor_1,...,valor_m)]

Actualización de registros (UPDATE):


UPDATE nombre_tabla
SET [atributo_1 = valor_1,..., atributo_r = valor_r]
[WHERE condición]
/* atributo = valor, atributo LIKE '<>' , o cualesquiera otras condiciones válidas*/

Eliminación de registros (DELETE):


DELETE FROM nombre_tabla
[WHERE condición]
/* atributo = valor, atributo LIKE '<>' , o cualesquiera otras condiciones válidas*/

Selección de información (SELECT):


SELECT [DISTINCT] datos_a_seleccionar
FROM tablas_y_relaciones
[WHERE condiciones]
[GROUP BY atributos_agrupación]
[HAVING condiciones_por_grupos]
[ORDER BY atributo_ordenación [DESC] [, atributo_2 [DESC]...]];

Algunas referencias:

• Tech on the Net


• W3Schools
• SQLzoo
• Documentación detallada sobre SQL de la UoC
Bases de Datos 2020 - 2021

Relación 5 - Introducción a SQL

Problema 1.
Consideremos que tenemos una base de datos con las siguientes tablas
PROVEEDORES ENVIOS
IDP PNOMBRE CATEGORIA CIUDAD IDP IDT IDC CANT
P1 CARLOS 20 SEVILLA P1 T1 C1 200
P2 JUAN 10 MADRID P1 T4 C1 700
P3 JOSE 30 SEVILLA P2 T1 C3 400
P4 INMA 20 SEVILLA P2 T2 C3 200
P5 EVA 30 CACERES P2 T3 C3 200
P2 T4 C3 500
COMPONENTES P2 T5 C3 600
IDC CNOMBRE COLOR PESO CIUDAD P2 T6 C3 400
C1 X3A ROJO 12 SEVILLA P2 T7 C3 800
C2 B85 VERDE 17 MADRID P2 T2 C5 100
C3 C4B AZUL 17 MALAGA P3 T1 C3 200
C4 C4B ROJO 14 SEVILLA P3 T2 C4 500
C5 VT8 AZUL 12 MADRID P4 T3 C6 300
C6 C30 ROJO 19 SEVILLA P4 T7 C6 300
P5 T2 C2 200
ARTICULOS P5 T4 C2 100
IDT TNOMBRE CIUDAD P5 T4 C5 500
T1 CLASIFICADORA MADRID P5 T7 C5 100
T2 PERFORADORA MALAGA P5 T2 C6 200
T3 LECTORA CACERES P5 T4 C1 100
T4 CONSOLA CACERES P5 T4 C3 200
T5 MEZCLADORA SEVILLA P5 T4 C4 800
T6 TERMINAL BARCELONA P5 T5 C5 400
T7 CINTA SEVILLA P5 T4 C6 500
La tabla PROVEEDORES representa los datos de proveedores de componentes para
la fabricación de artı́culos y su ciudad de residencia. La tabla COMPONENTES indica
la información de piezas utilizadas en la fabricación de diferentes artı́culos, indicándose el
lugar de fabricación de dichos componentes. La tabla ARTICULOSproporciona informa-
ción sobre los diferentes artı́culos que se fabrican y el lugar de montaje del mismo. Por
últimos, la tabla ENVIOS proporciona información sobre los suministros realizados por
los diferentes proveedores de determinadas cantidades de componentes asignadas para la
elaboración del artı́culo correspondiente.
La información relativa a estas tablas la puedes encontrar en el fichero
ejemploComponentes.sql. Puedes importarlo en phpMyAdmin o abrirlo desde MySQL-
Workbench y ejecutarlo.
Se pide:
Obtenga, para cada uno de los siguientes apartados, una sentencia SQL que permita
obtener la información pedida (pruébelo en MySQL):

1
1. Obtener todos los detalles de todos los artı́culos de CACERES.

2. Obtener todos los valores (distintos) de IDP para los proveedores que abastecen el
artı́culo T1;

3. Obtener la lista de pares de atributos (COLOR, CIUDAD) de la tabla componentes


eliminando los pares duplicados.

4. Obtener de la tabla de artı́culos los valores de IDT y CIUDAD donde el nombre de


la ciudad acaba en D o contiene al menos una E.

5. Obtener los valores de IDP para los proveedores que suministran para el artı́culo
T1 el componente C1.

6. Obtener los valores de TNOMBRE en orden alfabético para los artı́culos abastecidos
por el proveedor P1.

7. Obtener los valores de IDC para los componentes suministrados para cualquier
artı́culo de MADRID.

8. Obtener todos los valores de IDC de los componentes tales que ningún otro compo-
nente tenga un valor de peso inferior.

9. Obtener los valores de IDP para los proveedores que suministren los artı́culos T1 y
T2. Recuerda que Mysql no tiene el operador INTERSECT.

10. Obtener los valores de IDP para los proveedores que suministran para un artı́culo
de SEVILLA o MADRID un componente ROJO.

11. Obtener, mediante subconsultas (SELECT anidados), los valores de IDC para los
componentes suministrados para algún artı́culo de SEVILLA por un proveedor de
SEVILLA.

12. Obtener los valores de IDT distintos para los artı́culos que usan al menos un com-
ponente que se puede obtener con el proveedor P1.

13. Obtener todas las ternas (CIUDAD1, IDC, CIUDAD2) tales que un proveedor de
la CIUDAD1 suministre el componente especificado para un artı́culo montado en la
CIUDAD2.

14. Repetir el ejercicio anterior pero sin recuperar las ternas en los que los dos valores
de ciudad sean los mismos.

15. Obtener el número de suministros, el de artı́culos distintos suministrados y la can-


tidad total de artı́culos suministrados por el proveedor P2.

16. Para cada artı́culo y componente suministrado obtener los valores de IDC, IDT y
la cantidad total correspondiente.

17. Obtener los valores de IDT de los artı́culos abastecidos al menos por un proveedor
que no sea de MADRID y que no sea de la misma ciudad en la que se monta el
artı́culo.

2
18. Obtener los valores de IDP para los proveedores que suministran al menos un com-
ponente suministrado al menos por un proveedor que suministra al menos un com-
ponente ROJO.

19. Obtener los identificadores de artı́culos IDT para los que se ha suministrado algún
componente del que se haya suministrado una cantidad media superior a 500 artı́cu-
los.

20. Seleccionar los identificadores de proveedores que hayan realizado algún envı́o con
Cantidad mayor que la media de los envı́os realizados para el componente a que
corresponda dicho envı́o.

21. Seleccionar los identificadores de componentes suministrados para el artı́culo ’T2’


por el proveedor ’P2’.

22. Seleccionar todos los datos de los envı́os realizados de componentes cuyo color no
sea ’ROJO’.

23. Seleccionar los identificadores de componentes que se suministren para los artı́culos
’T1’ y ’T2’.

24. Seleccionar el identificador de proveedor y el número de envı́os de componentes de


color ’ROJO’ llevados a cabo por cada proveedor.

25. Seleccionar los colores de componentes suministrados por el proveedor ’P5’.

26. Seleccionar los datos de envı́o y nombre de ciudad de aquellos envı́os que cumplan
que el artı́culo, proveedor y componente son de la misma ciudad.

27. Seleccionar los nombres de los componentes que son suministrados en una cantidad
total superior a 500.

28. Seleccionar los identificadores de proveedores que residan en Sevilla y no suministren


más de dos artı́culos distintos.

29. Seleccionar los identificadores de artı́culos para los cuales todos sus componentes se
fabrican en una misma ciudad.

30. Seleccionar los identificadores de artı́culos para los que se provean envı́os de todos
los componentes existentes en la base de datos.

31. Seleccionar los códigos de proveedor y artı́culo que suministran al menos dos com-
ponentes de color ’ROJO’.

3
Problema 2.
Consideremos una base de datos con las siguientes relaciones:

La información relativa a estas tablas la puedes encontrar en el fichero


ejemploComponentes.sql. Puedes importarlo en phpMyAdmin o abrirlo desde MySQL-
Workbench y ejecutarlo. Igualmente, puedes operar con él, simplificando algunos aspectos
menores de notación, en SQLite.
Se pide:
Obtenga, para cada uno de los siguientes apartados, una sentencia SQL que permita
obtener la información pedida:

1. Obtener los datos de todos los clientes de Madrid.

2. Obtener los nombres de todas las marcas de coches ordenadas alfabéticamente.

3. Obtener el identificador de todos los concesionarios cuya cantidad distribuida es


mayor que 18.

4. Obtener el identificador de todos los concesionarios cuya cantidad distribuida está


comprendida entre 10 y 18, ambos inclusive. Realizarlo de dos maneras distintas.

5. Obtener el identificador de todos los concesionarios cuya cantidad distribuida está


comprendida entre 10 y 18, ambos exclusive.

6. Obtener el identificador de los concesionarios que han adquirido más de 10 coches


de algún tipo, o menos de 5 (como se indica, de un tipo, no en total).

7. Obtener todas las parejas de identificadores de marcas y clientes que sean de la


misma ciudad.

4
8. Obtener todas las parejas de identificadores de clientes y marcas que no sean de la
misma ciudad.

9. Obtener los códigos de los coches distribuidos por algún concesionario de Barcelona.

10. Obtener el código de los coches vendidos a clientes de Madrid.

11. Obtener los códigos de los coches adquiridos por un cliente de Madrid en un conce-
sionario de Madrid.

12. Obtener el código de los coches comprados en un concesionario de la misma ciudad


del cliente que lo compra.

13. Obtener los códigos de los coches comprados en un concesionario de distinta ciudad
que el cliente que lo compra.

14. Obtener todas las parejas de nombres de marcas que sean de la misma ciudad.

15. Obtener las parejas de modelos de coches cuyo nombre es el mismo y cuya marca
es de Bilbao.

16. Obtener todos los códigos de los coches cuyo nombre empiece por c.

17. Obtener todos los códigos de los coches cuyo nombre no contiene ninguna a. R.
Obtener el número total de nombres de marcas de coche que son de Madrid.

18. Obtener la media de la cantidad de coches que distribuyen todos los concesionarios.

19. Obtener el identificador de cliente con la numeración más alta de todos los clientes
de Madrid.

20. Obtener el identificador de cliente con numeración más baja de los que han comprado
un coche blanco.

21. Obtener el identificador de los concesionarios cuyo número de coches en stock (coches
que distribuyen) no es nulo.

22. Obtener el identificador y nombre de las marcas de coches cuya segunda letra del
nombre de la ciudad de origen sea una i.

23. Obtener el identificador de los clientes que han comprado algún coche a un conce-
sionario de Madrid.

24. Obtener el color de los coches vendidos por el concesionario acar.

25. Obtener el código de los coches vendidos por algún concesionario de Madrid. Rea-
lizarlo de dos formas: sin y con exists.

26. Obtener el nombre y modelo de los coches vendidos por algún concesionario de
Barcelona.

27. Obtener todos los nombre de los clientes que hayan adquirido algún coche del con-
cesionario dcar.

28. Obtener el nombre y apellido de los clientes que han adquirido un coche modelo gti
de color blanco.

5
29. Obtener el nombre y apellido de los clientes que han adquirido un automóvil a un
concesionario de Madrid que posea actualmente coches en stock del modelo gti.

30. Obtener el nombre y apellido de los clientes con identificador menor que el del cliente
Juan Martı́n.

31. Obtener el nombre y apellido de los clientes cuyo identificador es menor que el de
los clientes de Barcelona.

32. Obtener el nombre y apellido de los clientes cuyo nombre empieza por a y cuyo
identificador es mayor que el de todos los clientes de Madrid.

33. Obtener el nombre y apellido de los clientes cuyo nombre empieza por a y cuyo
identificador es mayor que el de alguno de los clientes de Madrid.

34. Obtener el nombre y apellido de los clientes cuyo nombre empieza por A y: cuyo
identificador es mayor que el de alguno de los clientes de Madrid, o menor que el de
todos los de Valencia.

35. Obtener el nombre y apellido de los clientes que han comprado como mı́nimo un
coche blanco y otro rojo.

36. Obtener el identificador de los clientes cuya ciudad sea la última de la lista alfabética
de las ciudades donde hay concesionarios.

37. Obtener la media de los automóviles que cada concesionario tiene actualmente en
stock (es decir, los que distribuye).

38. Obtener el identificador del concesionario que no sea de Madrid cuya media de
vehı́culos en stock sea la más alta de todas las medias.

39. Obtener usando exists el identificador de los clientes que hayan adquirido por lo me-
nos alguno de los coches que ha sido vendido por el concesionario cuyo identificador
es 1.

40. Obtener los identificadores de los clientes que sólo han comprado coches al conce-
sionario 1.

41. Obtener los nombres de los clientes que no han comprado ningún coche rojo a ningún
concesionario de Madrid.

42. Obtener el nombre de los clientes que sólo han comprado en el concesionario 1.

43. Obtener el código de coche de aquellos automóviles comprados por todos los clientes
de Madrid.

44. Obtener el código de coche de aquellos automóviles de color rojo y de modelo gti
que han sido comprados por todos los clientes cuyo apellido comienza por g.

45. Obtener el identificador de los clientes que han adquirido por lo menos los mismos
automóviles que el cliente Luis Garcı́a.

46. Obtener el identificador de los concesionarios que han vendido el mismo coche a
todos los clientes.

También podría gustarte