lunes, 4 de julio de 2011

Consultas Complejas

Consultas complejas

En la mayor parte de los casos es necesario usar en una consulta varias tablas para llegar a obtener la información deseada.

Por lo general se suelen combinar registros procedentes de dos o más tablas a partir de valores coincidentes en un campo común. Otras veces es preciso hacer subconsultas, o lo que es lo mismo, crear mediante sentencias SELECT tablas temporales de datos que forman parte a su vez de la cláusula FROM de otra sentencia SELECT. En todos estos casos, donde las posibles combinaciones de elementos pueden ser muchas, no hay que olvidar el factor eficiencia.

Combinación de tablas
Para este ejemplo se va a añadir una nueva tabla a la base de datos de contactos. Se trata de la tabla DIRECCION y cuenta con los siguientes campos: ID (identificador único de los contactos), DIRECCION (dirección completa del contacto). Como se puede observar se trata de una tabla muy sencilla. Cada contacto de la tabla CONTACTO puede tener una o más direcciones, lo que significa varios registros de la tabla DIRECCION.

La siguiente consulta muestra cómo se puede obtener una lista con los nombres de los contactos y las posibles direcciones:

SELECT NOMBRE, DIRECCION
FROM CONTACTOS, DIRECCION
WHERE CONTACTOS.ID = DIRECCION.ID

Los nombres de las tablas aparecen en la cláusula FROM separados por comas. El campo que guardan en común, en este caso el campo ID, es el nexo que permite relacionar la información de ambas tablas. Como el nombre de dicho campo es igual en las dos, es necesario calificarlo para que la base de datos sea capaz de saber a qué tabla corresponde la referencia. Esto se lleva a cabo poniendo delante del nombre del campo el nombre de tabla seguido de un punto.

Al principio puede resultar bastante confuso llegar a entender de qué forma se producen las combinaciones de la tablas en este tipo de sentencias SQL. El siguiente ejemplo utiliza unas tablas muy sencilla para ilustrar de qué modo se tratan las combinaciones de tablas.

TABLA 1

ID

VALOR

1

A

2

B

3

C

TABLA 2

ID

VALOR

1

D

2

E

3

F

Una consulta como la que sigue:

SELECT TABLA1.ID, TABLA1.VALOR, TABLA2.ID,
TABLA2.VALOR
FROM TABLA1, TABLA2;

daría lugar al producto cartesiano de ambas tablas:

Lo anterior significa que por cada registro de la tabla TABLA1 se obtienen tantas combinaciones como registros hay en la tabla TABLA2. En el momento que se introduce en la cláusula WHERE la condición que relaciona los campos comunes, el número de registros del resultado se restringe como se puede contemplar a continuación:

SELECT TABLA1.ID, TABLA1.VALOR, TABLA2.ID,
TABLA2.VALOR
FROM TABLA1, TABLA2
WHERE TABLA1.ID = TABLA2.ID

Tabla1.ID

Table1.valor



Tabla2.ID

Tabla2.Valor

1

A



1

D

2

B



2

E

3

C



3

F

Subconsultas
Hasta el momento todas las condiciones que se han aplicado en la cláusula WHERE han consistido en comparar el valor de un campo con un literal –es decir, con una constante, ya sea una cadena de texto, un número, etc.– o bien en relacionar dos campos que pertencen a tablas distintas. Existe una posibilidad más y es la que proporcionan las subconsultas. De manera informal se puede decir que una subconsulta no es más que una consulta dentro de otra consulta, o lo que es lo mismo, una sentencia SELECT que forma parte de otra sentencia SELECT. La siguiente consulta muestra un ejemplo:

SELECT COUNT(*)
FROM CONTACTOS
WHERE ID NOT IN (SELECT DISTINCT ID FROM
DIRECCION)

De lo anterior se deduce que, a la hora de calcular cuántos elementos hay en la tabla CONTACTOS, solamente se van a tener en cuenta aquellos cuyo ID no aparece en la tabla DIRECCION. En otras palabras, la consulta anterior determina el número total de contactos para los que no se ha registrado una dirección.

Las subconsultas también pueden aparecer en la cláusula FROM de las sentencias SELECT. La siguiente muestra un ejemplo típico:

SELECT NOMBRE, CUENTA
FROM CONTACTOS, (SELECT ID, COUNT(*) AS CUENTA
FROM DIRECCION
GROUP BY ID) TMP
WHERE CONTACTOS.ID = TMP.ID

La subcosulta interna utiliza la cláusula GROUP BY para obtener una tabla de datos formada por dos campos: el primero es el ID (identificador único de un contacto) y el segundo es la cuenta de las veces que aparece ese ID en la tabla DIRECCION, o lo que es lo mismo, el número de direcciones que hay para ese contacto. Rodear con paréntesis la consulta y poner a continuación el nombre TMP es equivalente a indicar a la base de datos que los resultados producidos por esa consulta van a constituir una tabla temporal llamada TMP.

La consulta exterior combina las tablas CONTACTOS y TMP utilizando el campo que guardan en común, el campo ID. El resultado que se obtiene es una lista de los nombres de los contactos y el número de direcciones que hay para cada uno de ellos. La utilizados en subconsultas y combinación de tablas pueden llegar a complicarse todo lo que se desee. Así por ejemplo, se podría obtener el número total de contactos para los que no se ha registrado una dirección partiendo de la consulta anterior, es decir, por una vía distinta a la utilizada al comienzo de este apartado:

SELECT COUNT(*)
FROM (
SELECT NOMBRE, CUENTA
FROM CONTACTOS, (SELECT ID, COUNT(*) AS CUENTA
FROM DIRECCION
GROUP BY ID) TMP
WHERE CONTACTOS.ID = TMP.ID
)
WHERE CUENTA = 0

No hay comentarios:

Publicar un comentario