Beruflich Dokumente
Kultur Dokumente
Carlos E. Cuesta.
Departamento de Informática (ATC, CCIA, LSI)
El lenguaje del Álgebra Relacional consta de seis operadores básicos, tres binarios y tres mona-
rios: la unión (R ∪ S), la diferencia (R − S), el producto cartesiano (R × S), la proyección
(πX (R)), la selección (σF (R)) y el renombrado (ρX (R)). Codd demostró que este álgebra
–es decir, este conjunto de operadores– es relacionalmente completo, lo que significa que cual-
quier acceso a la información contenida en una Base de Datos Relacional puede ser expresado
mediante una combinación de dichos operadores.
Sin embargo, estos operadores no expresan directamente una serie de operaciones habituales
en los procesos de consulta. Dada su frecuencia, resulta rentable definir operadores especı́ficos
para dichas operaciones, de modo que se puedan utilizar como si fueran primitivos. Por supues-
tos, estos nuevos operadores pueden ser especificados a partir de los básicos (debido precisamente
a la completud relacional de los mismos), por lo que reciben el nombre de operadores derivados.
Todos ellos son binarios, y se describen brevemente a continuación.
Intersección
Es el más sencillo e inmediato. Se representa con la sintaxis R ∩ S. Su semántica es análoga
a la del operador homónimo de la Teorı́a de Conjuntos. Es decir, para dos relaciones R y S
del mismo grado y con los mismos atributos, devuelve el conjunto de tuplas comunes a ambas
relaciones. Su descripción en función de los operadores básicos es inmediata:
R ∩ S ≡ R − (R − S) ≡ S − (S − R)
Intuitivamente equivale a la operación que extrae todas las tuplas comunes a dos relacio-
nes dadas, análoga por tanto a una conjunción lógica (∧).
Cociente
Es el más complejo, pero también el más potente de los operadores del Álgebra Relacional. Se
expresa mediante la sintaxis A ÷ B, notación tradicionalmente asociada al cociente aritmético.
De hecho, al igual que ocurre en el dominio de los números, el cociente será la operación inversa
al producto (cartesiano), aunque la correspondencia no resulta obvia a primera vista.
La operación se define para dos relaciones R y S, de grados r y s respectivamente, tales que
r > s; y donde se cumple además que S 6= ∅. En tal caso, se dice que el cociente está definido,
1
esto es, que R es divisible entre S 1 . Entonces, el cociente T de esas dos relaciones (T = R÷S) es
el conjunto de las tuplas t de grado (r − s), tales que para toda tupla u de S, la tupla compuesta
ht, ui está en R. Es decir:
2
Agrupando los atributos se puede obtener una expresión más clara. Ası́, se denominará B al
conjunto de los s atributos comunes a las dos relaciones (es decir, todos los de S), y A al resto
(es decir, los r − s atributos exclusivos de R). En tal caso, el esquema de relación del dividendo
tiene la forma R(A, B), el del divisor tiene la forma S(B), y por tanto el del cociente será T (A).
La expresión resultante tiene esta forma simplificada:
Esto significa lo siguiente: se toman las columnas A de R, es decir, todos los fragmentos de
tupla (πA (R)) que podrı́an aparecer en el resultado. El conjunto de estos fragmentos se multiplica
por la relación S, con lo que se obtienen todas las combinaciones posibles (πA (R) × S); lo que
incluye todas las tuplas de R, pero también algunas falsas. Por tanto, al restar a este conjunto
la relación R original, se obtiene la lista de todas las posibles tuplas espurias ((πA (R) × S) − R).
Al proyectar los atributos A de esta lista, se obtiene la relación de todos los fragmentos de tupla
que no pueden formar parte del cociente (πA ((πA (R) × S) − R)). Por lo tanto, al restar esta
relación del conjunto de los que podrı́an formar parte, se obtiene el conjunto de los que, en
efecto, están en el cociente.
Por supuesto, el orden de las columnas no importa; los atributos de A no tienen por qué ser
los primeros, ni los de B tienen por qué seguir la misma secuencia en las dos relaciones. Sin
embargo, suelen indicarse con el mismo orden para facilitar la legibilidad.
El significado intuitivo de esta operación es difı́cil de expresar; básicamente, extrae la infor-
mación que complementa a todo un conjunto de información que se tiene previamente.
Es mucho más fácil verlo cuando el grado de S es uno: en ese caso, el cociente expresa toda
la información que es común a todo un conjunto de objetos o conceptos dado. Ha-
bitualmente, se solicita mediante frases del tipo “indique el conjunto de elementos-A que tienen
la relación Z con todos los objetos B” 3 .
Un sencillo ejemplo de uso de esta operación es el siguiente:
R: A B C D S: C D R ÷ S: A B
1 2 3 5 3 5 1 2
4 3 5 9 2 7
3 2 8 1
1 2 2 7
1 3 2 7
Otro ejemplo, que muestra más claramente el objetivo de este operador (incluso actuando
sobre una única tabla), podrı́a ser el siguiente. Sea la tabla COCHES(Id, Modelo, Color), se
quiere obtener una lista de todos los modelos para los que hay coches de todos los colores. La
respuesta es (πM odelo, Color (Coches)÷πColor (Coches)), tal como se desarrolla a continuación para
un caso concreto.
3
Más adelante se revisa un ejemplo concreto de este tipo, en el que B es un conjunto de colores, y A una lista
de modelos de coches. La relación Z es el hecho de que exista un coche de cierto modelo y con cierto color.
3
Coches πM odelo, Color (Coches) πColor (Coches)
Id Modelo Color Modelo Color Color
C1 Jaguar Rojo Jaguar Rojo Rojo
C2 Jaguar Gris Jaguar Gris Gris
C3 Jaguar Verde Jaguar Verde Verde
C4 Jaguar Verde TransAm Rojo Azul
C5 TransAm Rojo TransAm Azul
C6 TransAm Azul Daimler Gris πM,C (Co) ÷ πC (Co)
C7 Daimler Gris Jaguar Azul Modelo
C9 Jaguar Azul TransAm Verde Jaguar
C10 TransAm Verde
SELECT Modelo
FROM Coches C1
WHERE NOT EXISTS (SELECT Color
FROM Coches C2
WHERE NOT EXISTS (SELECT ∗
FROM Coches C3
WHERE C1.Modelo = C3.Modelo AND
C2.Color = C3.Color))
Reunión (Join)
También es conocida como composición, pero habitualmente se menciona, sin embargo, mediante
el término en inglés. No añade ninguna potencia semántica al álgebra (en realidad persigue el
mismo objetivo que el producto cartesiano), pero permite mantener bajo control el tamaño de
las relaciones resultantes, que tiende a crecer rápidamente con toda operación-producto.
Sean dos relaciones R y S cualesquiera (de grados r y s, respectivamente), se define la
φ-reunión de estas relaciones sobre sus columnas (atributos) i y j, respectivamente (tales que
i ≤ r y j ≤ s), como el conjunto de todas las tuplas obtenidas combinando las tuplas de R y S,
cuando se cumple que la columna i-ésima (procedente de R) está en relación φ con la columna
j-ésima (procedente de S)4 .
La relación φ puede ser cualquiera, pero habitualmente se trata de la igualdad (=), que es
el caso arquetı́pico (mencionado a menudo en la bibliografı́a como equijoin), o de una relación
de orden (>, ≥, ≤, <), realizada habitualmente entre campos de tipo numérico o fecha.
4
Una vez que R y S se han reunido en la nueva relación, que tendrá grado r + s, y asumiendo que se mantiene
el orden de los atributos, poniendo en primer lugar los r de R, se puede decir que “la columna i-ésima está en
relación φ con la columna (r + j)-ésima” de la nueva relación. Se sigue esta misma idea en la posterior equivalencia
del operador derivado.
4
Se expresa mediante la sintaxis siguiente, y su traducción a los operadores básicos es inme-
diata, ya que se trata simplemente de una restricción sobre el producto cartesiano:
1 S ≡ σiφ(r+j) (R × S)
Riφj
Su función intuitiva es muy sencilla: reúne toda la información relativa a un tema dado,
considerando solamente aquélla que es a priori coherente con la pregunta (esto es, con la consulta
que se está intentando hacer), e ignorando el resto. Su intención es pues análoga a la del producto
cartesiano (×), ya que tiene como objetivo reunir información procedente de tablas diferentes
en un único punto (un único elemento del modelo, es decir, una tabla). De hecho, el producto
es la única forma de reunir información que de otra forma se encuentra dispersa; sin embargo,
tiene el problema de la explosión combinatoria: el tamaño de las tablas-producto tiende a crecer
demasiado rápidamente.
La importancia del join deriva justamente de esto: al indicar desde el principio cuál es la
condición que hará a ciertas tuplas interesantes, se controla el tamaño de las tablas resultantes,
ya que todas las combinaciones irrelevantes se descartan de inmediato. Por supuesto, si el
operador se implementase mediante su traducción a los básicos, el producto se realizarı́a de
todos modos; pero en una implementación real, una versión optimizada del join podrı́a evitar
la generación de información espuria.
El siguiente ejemplo muestra dos tablas con datos sobre actores y actrices; se pide el nombre
de las actrices con mayor edad que algún actor 5 . La expresión algebraica correspondiente a esta
pregunta, y un ejemplo de aplicación, se indican a continuación:
πIdentidad (ActoresEdad<Anyos
1 Actrices)
Actores Actrices 1
Actores Edad<Anyos Actrices
Nombre Edad Identidad Anyos Nombre Edad Identidad Anyos
G. Peck 80 S. Sarandon 50 K. Reeves 23 S. Sarandon 50
K. Reeves 23 N. Portman 18 T. Cruise 30 S. Sarandon 50
T. Cruise 30 J. Roberts 28 K. Reeves 23 J. Roberts 28
πIdentidad ((ActricesEdad<Anyos
1 Actores) ÷ Actores)
5
En el ejemplo se han usado nombres diferentes para atributos similares en ambas relaciones,
con el fin de evitar cualquier confusión con el join natural. En realidad, el resultado hubiera sido
exactamente el mismo aun en el caso de que los atributos de ambas relaciones hubieran tenido el
mismo nombre (Nombre, Edad); pero en ese caso deberı́a usarse el operador de renombrado (ρ)
sobre atributos, ya que el modelo relacional prohı́be expresamente que una tabla tenga nombres
de columna duplicados. El operador no considera este caso, por lo que la responsabilidad de
controlarlo cae completamente en el diseñador de la consulta.
La ventaja del operador es mayor de la que parece: no sólo se tiene una notación más
compacta para una operación muy habitual, sino que el tamaño de los cálculos intermedios
puede reducirse en gran medida. Pero en realidad, y a pesar de todo lo que se ha dicho, ante
todo el join sólo es importante porque generaliza a una operación aún más frecuente: el join
natural, que es absolutamente fundamental en el álgebra relacional.
Grosso modo, basta con realizar el producto cartesiano (×), seleccionar (σ) las tuplas con los
atributos iguales, y proyectar (π) el resultado para dejar únicamente las columnas relevantes.
La descripción formal indicada tiene en realidad dos sutilezas: en primer lugar, se asume que los
atributos A1 , A2 , . . . , Ak son todos los atributos que tienen el mismo nombre tanto en R como
en S. De este modo, la selección (σ) elige solamente aquellos en los que los valores de todos ellos
son simultáneamente iguales.
Menos elegante es la forma de la proyección (π). Dado que la copia final ha de eliminar
duplicados, se asume que disponemos de un ı́ndice ordenado i1 , i2 , . . . , im , que incluye a todos
los atributos no comunes, y una única copia de cada uno de los comunes. De este modo, se
seleccionan las m columnas relevantes, y se descarta la segunda copia de las k comunes6 .
6
De lo que se sigue que m + k = r + s. En realidad, esto no es más que un artificio para simplificar la definición.
En la práctica, no se usa un ı́ndice {ij }j=1...m , sino que simplemente se descartan las k repetidas.
6
El objetivo del join natural es reunir toda la información acerca de un mismo objeto o
concepto, que estaba previamente dispersa en dos (o más) relaciones. Éste es el tipo de consulta
más normal, y sin embargo resulta complejo expresarla en términos de los operadores básicos.
De hecho, la única operación capaz de relacionar dos tablas distintas es el producto cartesiano,
que es tedioso y complejo, y genera un gran número de combinaciones innecesarias. Resulta
mucho más natural esta reunión basada en el contenido, que sólo maneja información relevante:
de ahı́ el nombre del operador. No obstante, sigue siendo un operador derivado.
Es un operador requerido por el propio modelo relacional, ya que se adapta perfectamente
a la idea de recorrer un enlace entre dos relaciones para realizar una consulta. En efecto,
resulta totalmente coherente con la definición de clave ajena como un conjunto de atributos de
la relación R1 cuyo contenido ha de coincidir con la clave primaria de la relación referenciada,
R2 . Al hacer un join natural entre dos tablas de esta forma, simplemente se seleccionan las
tuplas en las que la clave primaria de R2 coindice con la clave ajena de R1 , y se descartan los
duplicados. El resultado equivale a haber navegado por el enlace desde R1 hacia R2 .
Un ejemplo sencillo de join natural es el siguiente, que tiene como rasgo notable hacer la
fusión de dos columnas (atributos) homónimas, A y C, en lugar de solamente una, que es lo más
habitual cuando se trata de recorrer una clave ajena.
R: A B C D S: A C E R1S: A B C D E
1 3 5 7 1 5 2 1 3 5 7 2
3 2 9 1 1 5 9 1 3 5 7 9
2 3 5 4 3 9 2 3 2 9 1 2
2 3 7
Al igual que el producto cartesiano, con el que no deja de guardar una estrecha relación, el
join natural es conmutativo y asociativo: no resulta afectado, pues, por el orden en el que se
realicen las operaciones.