Consultas combinadas.
JOINS
Consultas combinadas.
Habitualmente cuando necesitamos recuperar la informacin de una base de datos nos
encontramos con que dicha informacin se encuentra repartida en varias tablas, referenciadas a
travs de varios cdigos. De este modo si tuviramos una tabla de ventas con un campo cliente,
dicho campo contendra el cdigo del cliente de la tabla de cliente.
Sin embargo est forma de almacenar la informacin no resulta muy til a la hora de consultar
los datos. SQL nos proporciona una forma fcil de mostrar la informacin repartida en varias
tablas, las consultas combinadas o JOINS.
Las consultas combinadas pueden ser de tres tipos:
Combinacin interna
Combinacin externa
Uniones
Combinacin interna.
La combinacin interna nos permite mostrar los datos de dos o ms tablas a travs de una
condicin WHERE.
Como ejemplo tenemos una tabla de coches, en la que tenemos referenciada la marca a travs
del cdigo de marca. Para realizar la consulta combinada entre estas dos tablas debemos
escribir una consulta SELECT en cuya clusula FROM escribiremos el nombre de las dos tablas,
separados por comas, y una condicin WHERE que obligue a que el cdigo de marca de la tabla de
coches sea igual al cdigo de la tabla de marcas.
Lo ms sencillo es ver un ejemplo directamente:
SELECT tCoches.matricula,
tMarcas.marca,
tCoches.modelo,
tCoches.color,
tCoches.numero_kilometros,
tCoches.num_plazas
FROM tCoches, tMarcas
WHERE tCoches.marca = tMarcas.codigo
La misma consulta de forma "visual" ...
Dmonos cuenta que hemos antepuesto el nombre de cada tabla a el nombre del campo, esto
no es obligatorio si los nombres de campos no se repiten en las tablas, pero es aconsejable para
evitar conflictos de nombres entre campos. Por ejemplo, si para referirnos al campo marca no
anteponemos el nombre del campo la base de datos no sabe si queremos el campo marca de la
tabla tCoches, que contiene el cdigo de la marca, o el campo marca de la tabla tMarcas, que
contiene el nombre de la marca.
Otra opcin es utilizar la clusula INNER JOIN. Su sintaxis es idntica a la de una
consulta SELECT habitual, con la particularidad de que en la clusula FROM slo aparece una
tabla o vista, aadindose el resto de tablas a travs de clusulas INNER JOIN .
SELECT [ALL | DISTINCT ]
<nombre_campo> [{,<nombre_campo>}]
FROM <nombre_tabla>
[{INNER JOIN <nombre_tabla> ON <condicion_combinacion>}]
[WHERE <condicion> [{ AND|OR <condicion>}]]
[GROUP BY <nombre_campo> [{,<nombre_campo >}]]
[HAVING <condicion>[{ AND|OR <condicion>}]]
[ORDER BY <nombre_campo>|<indice_campo> [ASC | DESC]
[{,<nombre_campo>|<indice_campo> [ASC | DESC ]}]]
El ejemplo anterior escrito utilizando la clusula INNER JOIN quedara de la siguiente manera:
SELECT tCoches.matricula,
tMarcas.marca,
tCoches.modelo,
tCoches.color,
tCoches.numero_kilometros,
tCoches.num_plazas
FROM tCoches
INNER JOIN tMarcas ON tCoches.marca = tMarcas.codigo
La clusula INNER JOIN permite separar completamente las condiciones de combinacin con
otros criterios, cuando tenemos consultas que combinan nueve o diez tablas esto realmente se
agradece. Sin embargo muchos programadores no son amigos de la clusula INNER JOIN, la
razn es que uno de los principales gestores de bases de datos, ORACLE, no la soportaba. Si
nuestro programa deba trabajar sobre bases de datos ORACLE no podamos utilizar INNER
JOIN. A partir de la versin ORACLE 9i Oracle soporta la clusula INNER JOIN.
Combinacin Externa
La combinacin interna es excluyente. Esto quiere decir que si un registro no cumple la
condicin de combinacin no se incluye en los resultados. De este modo en el ejemplo anterior si
un coche no tiene grabada la marca no se devuelve en mi consulta.
Segn la naturaleza de nuestra consulta esto puede ser una ventaja, pero en otros casos
significa un serio problema. Para modificar este comportamiento SQL pone a nuestra disposicin la
combinacin externa. La combinacin externa no es excluyente.
La sintaxis es muy parecida a la combinacin interna,
SELECT [ALL | DISTINCT ]
<nombre_campo> [{,<nombre_campo>}]
FROM <nombre_tabla>
[{LEFT|RIGHT OUTER JOIN <nombre_tabla> ON
<condicion_combinacion>}]
[WHERE <condicion> [{ AND|OR <condicion>}]]
[GROUP BY <nombre_campo> [{,<nombre_campo >}]]
[HAVING <condicion>[{ AND|OR <condicion>}]]
[ORDER BY <nombre_campo>|<indice_campo> [ASC | DESC]
[{,<nombre_campo>|<indice_campo> [ASC | DESC ]}]]
La combinacin externa puede ser diestra o siniestra, LEFT OUTER JOIN o RIGHT OUTER
JOIN. Con LEFT OUTER JOIN obtenemos todos los registros de en la tabla que situemos a la
izquierda de la clusula JOIN, mientras que con RIGHT OUTER JOIN obtenemos el efecto
contrario.
Como mejor se ve la combinacin externa es con un ejemplo.
SELECT
tCoches.matricula,
tMarcas.marca,
tCoches.modelo,
tCoches.color,
tCoches.numero_kilometros,
tCoches.num_plazas
FROM
LEFT OUTER JOIN tMarcas ON tCoches.marca = tMarcas.codigo
tCoches
Esta consulta devolver todos los registros de la tabla tCoches, independientemente de que
tengan marca o no. En el caso de que el coche no tenga marca se devolver el valor null para los
campos de la tabla tMarcas.
Visualmente (la consulta devuelve los datos en azul) ...
El mismo ejemplo con RIGHT OUTER JOIN.
SELECT tCoches.matricula,
tMarcas.marca,
tCoches.modelo,
tCoches.color,
tCoches.numero_kilometros,
tCoches.num_plazas
FROM tCoches
RIGHT OUTER JOIN tMarcas ON tCoches.marca = tMarcas.codigo
Esta consulta devolver los registros de la tabla tCoches que tengan marca relacionada y todos
los registros de la tabla tMarcas, tengan algn registro en tCoches o no.
Visualmente (la consulta devuelve los datos en azul) ...
Union
La clusula UNION permite unir dos o ms conjuntos de resultados en uno detrs del otro como
si se tratase de una nica tabla. De este modo podemos obtener los registros de ms de una tabla
"unidos".
La sintaxis corresponde a la de varias SELECT unidas a travs de UNION, como se muestra a
continuacin:
SELECT [ALL | DISTINCT ]
<nombre_campo> [{,<nombre_campo>}]
FROM <nombre_tabla>
[{LEFT|RIGHT OUTER JOIN <nombre_tabla> ON
<condicion_combinacion>}]
[WHERE <condicion> [{ AND|OR <condicion>}]]
[GROUP BY <nombre_campo> [{,<nombre_campo >}]]
[HAVING <condicion>[{ AND|OR <condicion>}]]
{
UNION [ALL | DISTINCT ]
SELECT [ALL | DISTINCT ]
<nombre_campo> [{,<nombre_campo>}]
FROM <nombre_tabla>
[{LEFT|RIGHT OUTER JOIN <nombre_tabla> ON
<condicion_combinacion>}]
[WHERE <condicion> [{ AND|OR <condicion>}]]
[GROUP BY <nombre_campo> [{,<nombre_campo >}]]
[HAVING <condicion>[{ AND|OR <condicion>}]]
}
[ORDER BY <nombre_campo>|<indice_campo> [ASC | DESC]
[{,<nombre_campo>|<indice_campo> [ASC | DESC ]}]]
Para utilizar la clusula UNION debemos cumplir una serie de normas.
Las consultas a unir deben tener el mismo nmero campos, y adems los campos deben ser del
mismo tipo.
Slo puede haber una nica clausula ORDER BY al final de la sentencia SELECT.
El siguiente ejemplo muestra el uso de UNION
SELECT tCoches.matricula,
tMarcas.marca,
tCoches.modelo,
tCoches.color,
tCoches.numero_kilometros,
tCoches.num_plazas
FROM tCoches
INNER JOIN tMarcas ON tCoches.marca = tMarcas.codigo
UNION
SELECT tMotos.matricula,
tMarcas.marca,
tMotos.modelo,
tMotos.color,
tMotos.numero_kilometros,
0
FROM tMotos
INNER JOIN tMarcas ON tMotos.marca = tMarcas.codigo;
Puede observarse el uso de la constante cero en la segunda lista de seleccin para hacer coincidir
el nmero y tipo de
campos que devuelve la consulta UNION.