CC42A: Bases de datos
Auxiliar: Álgebra Relacional

Profesores: Claudio Gutiérrez, Gonzalo Navarro
Prof. Auxiliar: Rodrigo Paredes

Parte 1. Álgebra relacional

El Álgebra Relacional es un lenguaje procedural para la manipulación de relaciones.

El álgebra relacional define nueve operaciones: unión, intersección, diferencia y producto (que vienen de la teoría de conjuntos de la matemática), selección, proyección, reunión y división (que son las que se aplican específicamente al modelo de datos relacional) y asignación (operación estándar de los lenguajes de computación) que le da un valor a un nombre, para la operación de asignación ocuparemos :=.
 

Primero veamos  los que vienen de la teoría de conjuntos

Unión : Operación del álgebra relacional que crea un conjunto unión de dos relaciones unión compatibles.

unión compatible: Dos o más relaciones que tienen columnas equivalentes en número y dominios.

Supongamos que:
VENDEDOR_SUBORDINADO {VENS_ID_VENDEDOR, VENS_NOMB_VENDEDOR, VENS_ID_JEFE, VENS_OFICINA, VENS_COMISION}
VENDEDOR_JEFE {VENJ_ID_VENDEDOR, VENJ_NOMB_VENDEDOR, VENJ_ID_JEFE, VENJ_OFICINA, VENJ_COMISION}

Si queremos calcular el conjunto de TODOS los vendedores:

VENDEDOR := VENDEDOR_SUBORDINADO  VENDEDOR_JEFE

Intersección : Operación del álgebra relacional que crea un conjunto intersección de dos relaciones unión compatibles.

Si queremos calcular el conjunto de los vendedores que son jefes y subordinados a la vez:

VENDEDOR_JEFE_SUBORDINADO := VENDEDOR_SUBORDINADO  VENDEDOR_JEFE

Diferencia -: Operación del álgebra relacional que crea un conjunto diferencia de dos relaciones unión compatibles. Ojo que la diferencia no es conmutativa.

Si queremos calcular quién (es) son jefe solamente (es decir, quien es el personaje que está en VENDEDOR_JEFE, pero que no está en VENDEDOR_SUBORDINADO):

VENDEDOR_JEFE_JEFE := VENDEDOR_JEFE  - VENDEDOR_SUBORDINADO

Producto *: Operación del álgebra relacional que crea el producto cartesiano de dos relaciones.

si A{X, Y} tiene los siguientes elementos
 
10
22
11
25

y B{W, Z} contiene:
 
33
54
37
98
42
100

Entonces el producto de A y B es:

C := A * B
 
10
22
33
54
10
22
37
98
10
22
42
100
11
25
33
54
11
25
37
98
11
25
42
100

Ojo que si hacemos el producto cartesiano de dos relaciones que tienen un atributo en común, vamos a tener un problema con el nombre de la columna, para ello se recomienda como regla general que el nombre de un atributo esta compuesto por:

  1. Una sigla que hace referencia al nombre de la relación
  2. Un subrayado
  3. El nombre del atributo
Ejemplo:
PRODUCTO {PROD_ID_PROD, PROD_NOMBRE, ...}
VENTA {VTA_ID_PROD, VTA_FECHA, ...}
 

Específicas del álgebra relacional

Selección SELECT: Operación del álgebra relacional que usa una condición para seleccionar filas de una relación.

Si quisiéramos resolver la siguiente consulta: Dar toda la información de los vendedores en la oficina de Tokyo.

VEND_TOKYO := SELECT (VENDEDOR : VEND_OFICINA = 'Tokyo')

Noten que las condiciones de selección (las que van después del ':') son similares a las usadas en la instrucciones IF.

Consulta: ¿Qué vendedores tienen ID 23?
SELECT (VENDEDOR : VEND_ID_VENDEDOR = 23)

Consulta: ¿Qué vendedores tienen trabajan en Tokio y tienen comisión superior a 11%?
SELECT (VENDEDOR : VEND_OFICINA = 'Tokyo' and VEND_COMISION > 11)

Proyección [.]: Operación del álgebra relacional que crea una relación borrando columnas de una relación existente.

A[X]
10
11

Ojo que la proyección genera conjuntos, luego si en la tabla original la subtupla seleccionada se repite, al proyectar sólo vemos la fila una vez.

Consulta: ¿Quiénes son los vendedores que tienen una comisión menor que 20%?

SELECT (VENDEDOR : VEND_COMISION < 11) [VEND_NOMBRE]

Reunión JOIN: Operación del álgebra relacional que conecta relaciones.

Hay tres casos:

  1. Reunión natural : Operación de reunión que conecta relaciones cuando las columnas comunes tienen iguales valores.
  2. Reunión theta: Operación  de reunión que conecta relaciones cuando los valores de determinadas columnas tienen una interrelación específica.
  3. Reunión externa: Expansión de la reunión natural que incluye todas las filas de ambas relaciones.
Reunión natural: Noten que la reunión natural hace la asociación de las llaves y atributos comunes solita, no hay que especificar nada.

Consulta: Adjunte la información de las ventas a la información sobre los vendedores.
JOIN(VENDEDOR, VENTA)

Consulta: Indique los nombres de los clientes que han comprado el producto 2518
A := SELECT (VENTA: VTA_ID_PROD = 2518)
B := JOIN (A, CLIENTE) [CLI_NOMBRE]

Consulta: ¿Quiénes han comprado lámparas de mesa?
A := SELECT (PRODUCTO : DESCRIPCION = 'lámpara de mesa')
B := JOIN (A, VENTA)
C := JOIN (B, CLIENTE) [CLI_NOMBRE]

Reunión theta: Considere la siguiente consulta:

Consulta: ¿Identifique los vendedores cuyos jefes obtienen una tasa de comisión por encima del 11%?

Para esto tenemos que hacer un JOIN de la tabla VENDEDORES con la tabla VENDEDORES !!, porque así podemos encontrar directamente cual es la comisión del jefe, pero el join natural intentara calzar todos los atributos (porque ambas tablas tienen los mismos atributos, es más es la misma tabla), así que haremos un JOIN pero especificando los atributos de calce.

VEND1 := VENDEDOR
VEND2 := VENDEDOR
A           := JOIN (VEND1, VEND2 : VEND1.VEND_ID_JEFE = VEND2.VEND_ID_VENDEDOR)
B           := SELECT (A : VEND2.VEND_COMISION > 11) [VEND1.VEND_NOMBRE]

Reunión externa: Primero se ejecuta una reunión natural. Entonces si un registro en una relación no se corresponde con un registro de la otra relación en la reunión natural, ese registro se añade a la relación que ha sido reunida y las columnas adicionales se llenan con valores nulos.

Consulta: Adjunte la información de las ventas a la información sobre los vendedores.

Solución inicial: JOIN (VENDEDOR, VENTA)

¿Pero qué pasa con los vendedores que no han hecho ventas?

OUTERJOIN (VENDEDOR, VENTA)  :)

División /: Operación del álgebra relacional que crea una nueva relación, seleccionando las filas en una relación que se corresponden con todas las filas en otra relación.

Consulta: Liste los vendedores que han vendido todos los productos.

PI := PRODUCTO [PROD_ID_PRODUCTO]
PI_VI := VENTA [PROD_ID_PRODUCTO, VTA_ID_VENDEDOR]
A := PI_VI / PI

Noten que en A sólo queda la columna VTA_ID_VENDEDOR, y se listan sólo los vendedores que han vendido a todos los productos.

Operador de asignación

Ya vimos que se usa para guardar nuevas relaciones que se generan mediante el uso de los operadores del álgebra relacional, y utiliza el símbolo :=.


Parte 2. Ejemplos

P1.- Consulta: ¿Cuál es la máxima tasa de comisión?

A := VENDEDOR [VEND_COMISION]
B := VENDEDOR [VEND_COMISION]
C := JOIN (A, B: A.VEND_COMISION > B.VEND_COMISION)
D := C [B.VEND_COMISION] // acá me quedo con la comisión menor :)
E := A - D
 

P2.- Considere el siguiente esquema:

CLIENTE{CLI_ID, CLI_NOMB, CLI_RENTA_ANUAL}
EMBARQUE{EMB_ID, EMB_ID_CLI, EMB_PESO, EMB_ID_CAMION, EMB_DESTINO}
Clave Foránea: EMB_CLI_ID referencia a CLI_ID en CLIENTE

¿Cuáles son los nombres de los clientes que han enviado paquetes a la ciudad de Sioux, Iowa?
 
A := JOIN(CLIENTE,EMBARQUE : CLI_ID = EMB_CLI_ID) equivalente al JOIN(CLIENTE,EMBARQUE) porque el atributo CLI_ID es el mismo que EMB_ID_CLI
B := SELECT (A : EMB_DESTINO = 'Sioux') En B guardo las filas que llegan a Sioux
C := SELECT (A : EMB_DESTINO = 'Sioux') En C guardo las filas que llegan a Iowa
D := B C Unión de dos relaciones unión compatibles
Respuesta := D[CLI_NOMB] Me quedo con los nombre solamente

¿A qué destinos han enviado paquetes los clientes con renta anual inferior a un millón
 
A := SELECT (CLIENTE : CLI_RENTA < 1000000) [CLI_ID] Calculo los clientes que tienen menos de un millón de renta, y sólo me quedo con el identificador
Respuesta := JOIN (A, EMBARQUE) [EMB_DESTINO] Hago el join de A con la relación de embarques

P3.- Considere el siguiente esquema:

CLIENTE{CLI_ID, CLI_NOMB, CLI_RENTA_ANUAL}
EMBARQUE{EMB_ID, EMB_ID_CLI, EMB_PESO, EMB_ID_CAMION, EMB_DESTINO}
Clave Foránea: EMB_CLI_ID referencia a CLI_ID en CLIENTE
Clave Foránea: EMB_DESTINO referencia a CIU_NOMBRE en CIUDAD
Clave Foránea: EMB_ID_CAMION referencia a CAM_ID en CAMION
CAMION{CAM_ID, CAM_NOMBRE_CHOFER}
CIUDAD{CIU_NOMBRE, CIU_POBLACION}

¿Cuáles son los nombres de la ciudades que han recibido envíos que pesan más de 100 libras?
 
A := SELECT (EMBARQUE : EMB_PESO > 100) [EMB_DESTINO] Selecciono los envíos que me interesan, y luego el identificador del destino
Respuesta := JOIN (A, CIUDAD) [CIU_NOMBRE]

Las ciudades que han recibido embarques de clientes que tienen una renta anual por encima de los 15 millones.
 
A := SELECT (CLIENTE : CLI_RENTA_ANUAL > 15000000) [CLI_ID] El id de los clientes con renta > 15000000
B := JOIN (A, EMBARQUES) [EMB_DESTINO] El id de las ciudades
Respuesta := JOIN (B, CIUDAD) [CIU_NOMBRE]

Clientes que han tenido envíos distribuidos por todos los choferes
 
A := CAMION[CAM_NOMBRE_CHOFER] Preparo el divisor
B := JOIN (EMBARQUES, CAMION) [EMB_ID_CLI, CAM_NOMBRE_CHOFER] Preparo el dividendo
C := B / A Hago la división
Respuesta := JOIN(C,CLIENTE) [NOMB_CLIENTE]

Clientes que envían todos sus embarques a una única ciudad
 
A := EMBARQUES [EMB_ID_CLI, EMB_DESTINO] Guardo las subtuplas que me interesan
B := A
C := A * B C es el producto cartesiano de A con B
D := SELECT (C : A.EMB_ID_CLI = B.EMB_ID_CLI) D guarda las filas de C con igual nombre de cliente
E := SELECT (D : A.EMB_DESTINO not = B.EMB_DESTINO) Me quedo con las filas de D con destino diferente
F := E[A.EMB_ID_CLI] Estos son los nombres de los clientes con más de un destino
G := EMBARQUE[EMB_ID_CLI] Estos son los clientes que hacen envíos
H := G - F Acá quedan los clientes con 1 destino
Respuesta := JOIN(H, CLIENTE)[CLI_NOMBRE] Uf!!, terminamos