Tutorial de SQL. SELECT Parte II

Anuncio
Published on The Cold Sun (http://www.thecoldsun.com)
Home > Printer-friendly PDF > Printer-friendly PDF
Tutorial de SQL. SELECT Parte II
Table of Contents [hide]
Introducción
Funcions de conjunto y Group By
Group By
Having
Joins
Inner Join
Outer Join
Introducción
En el artículo anterior vimos el uso más básico de la clausula SELECT de SQL, sin embargo apenas
arañamos la superficie en cuanto a la cantidad de tipos de selecciones que podemos hacer.
En este segundo artículo vamos a explorar las posibilidades de los comandos de conjunto que nos
permiten realizar operaciones sobre las filas que devolvemos (como devolver una suma, o el número de
filas) así como el uso de la orden GROUP BY que está íntimamente relacionado con lo anterior. Por otro
lado exploraremos las intersecciones que se pueden realizar entre consultas (JOIN).
Funcions de conjunto y Group By
Las funciones de conjunto (aggregate functions en inglés) son una serie de funciones aplicables a cada
columna devuelta por un SELECT que nos permiten realizar determinadas acciones sobre ellas. Ejemplo
de dichas funciones son obtener la media de una columna, obtener el número de columnas devueltas u
obtener el valor máximo de entre los resultados de una columna.
La sintaxis genérica podríamos definirla así
SELECT func1(col1), func2(col2), col3 FROM Tabla WHERE Condicion GROUP BY col3
Como vemos el uso de las funciones de conjunto va asociado al uso de la palabra GROUP BY. Más
adelante veremos algunos usos de esta palabra reservada, de momento vamos a ver algunos ejemplos:
Count: Probablemente la función de agrupación más usada, devuelve el número de ocurrencias de
la columna en cuestión.
SELECT Count(*) FROM Personas;
Nos devolverá el número de filas que hay en la tabla Personas, es completamente equivalente a, por
ejemplo
SELECT Count(Persona_Id) FROM Personas;
pero puede devolver un número distinto a
SELECT Count(Apellidos) FROM Personas;
esto se debe a que si especificamos una columna concreta nos contará [b]solo aquellas filas que no
tengan un valor null en dicha columna[/b] por lo que si existe una persona sin apellidos en nuestra tabla,
dicha persona no contará en la query (el caso de Persona_Id que es clave y por tanto no nula el
resultado es equivalente).
El caso concreto de "Count(*)" que nos devuelve la cantidad de registros de una tabla suele utilizarse para
mostrar el número total de personas o para, por ejemplo, organizar una vista paginada de dicha tabla.
También podemos, por supuesto contar solo aquellos registros que cumplen una condición
SELECT Count(*) FROM Personas WHERE Edad < 30;
obtendría el número de personas de nuestra base de datos cuya edad es menor que 30 años.
Avg: Del inglés "average", calcula la media de la columna dada, por ejemplo, si tenemos una tabla
llamada personas y queremos obtener la media de edad ...
SELECT Avg(Edad) FROM Personas;
o, por ejemplo, la media de edad de aquellas personas que ganan más de 30.000 € al año
SELECT Avg(Edad) FROM Personas WHERE Salario > 30000;
cuyo resultado puede ser algo como
Edad
31
Max y Min: Devuelven el valor máximo y minimo respectivamente de una columna, por ejemplo
SELECT Min(Edad) FROM Personas WHERE Salario > 30000;
nos permitirá saber quien es la persona de menor edad con un salario superior a los 30.000 € al año.
Esos son los principales y más usados, existen algunos otros como First y Last que obtienen el primer y
el último elemento respectivamente, y existen también funciones de grupo propias de cada proveedor de
base de datos que, por tanto, no son estándares de SQL.
Group By
El comando Group by está estrechamente relacionado con las funciones de agrupación y nos permite,
como su nombre, en inglés, indica, agrupar los resultados. Hasta ahora los ejemplos que hemos visto se
han limitado a realizar operaciones con una columna o con el total de filas. Así obteníamos la edad media o
el número de filas de una determinada tabla. Sin embargo en ocasiones podemos querer aplicar la función
de agrupación por "grupos". Por ejemplo, supongamos que tenemos una tabla con el estado de los
productos disponibles que pueden estar en disponibles, pedidos, agotados, o decatalogados.
Supongamos que lo que deseamos es saber cuantos productos de cada clase tenemos, si utilizamos la
siguiente consulta
SELECT Count(*), Estado FROM Productos;
obtendremos un error indicándonos que "Estado" debe estar dentro de una cláusula Group By. Esto es
así porque necesitamos indicarle al motor de SQL que queremos queagrupe los resultados teniendo en
cuenta el valor de esta columna, es decir, que primero determine que filas tienen el mismo valor para la
columna estado y luego, sobre dichas filas, por separado, aplique la función de agrupación. De esta forma
tendríamos:
SELECT Count(*) AS Total, Estado FROM Productos GROUP BY Estado
que nos proporcionaría una salida de este estilo
Total
Estado
1395
Disponibe
135
Pedido
13
Agotado
7
Descatalogado
Podemos aplicar el comando Group By a más de una columna para agrupar por varias columnas que
sean iguales, pero evidentemente si lo hacemos, nos agrupará los resultados por aquellos resultados que
tengan el contenido de ambas columnas exactamente igual, por lo que si coinciden en tan solo una
columna pero la otra difiere, se mostrarán como resultados distintos. Por ejemplo:
Ciudad, Universidad, Avg(Edad) FROM Alumnos WHERE Edad < 30 GROUP BY Ciudad,
Universidad;
SELECT
nos devolverá la edad media de todos los estudiantes que vivan en la misma ciudad y atiendan a la
misma universidad teniendo en cuenta tan solo aquellos estudiantes menores de 30 años.
Ciudad
Universidad
Edad
Madrid
Universidad Politécnica
23
Madrid
Universidad Autónoma
24
Toledo
Universidad Politécnica
26
Barcelona
Universidad de Barcelona
21
Barcelona
Universidad de Tarragona
24
Having
Para acabar de complementar las funciones de agrupación tenemos el operador Having. La función de
Having es, a las funciones de agrupación, lo que el Where es al comando select. De esta forma, el having
nos permitirá realizar filtrados sobre los resultados obtenidos en función del valor de la función de
agrupación, por ejemplo, volviendo a la consulta anterior podemos refinarla y obtener tan solo aquellos
resultados cuya edad media sea superior a 23 años.
Ciudad,
Universidad,
Avg(Edad)
Alumnos
Ciudad,
Universidad
Avg(Edad)
> 23 WHERE Edad < 30
SELECTBY
GROUP
HAVINGFROM
Joins
El término Join (juntar en inglés) se utiliza en SQL para definir una operación que unifica datos de dos (o
más) tablas en base a una o varias comparaciones entre las columnas de las tablas. Podemos definir dos
tipos de joins, los Inner Join y los Outer Join.
Personas
Coches
Inner Join
Un inner join mezcla los datos de dos tablas realizando el producto cartesiano entre ellas en función de lo
indicado en la clausula WHERE de estar esta presente. Si no indicamos ningún comando de comparación
en la clausula WHERE el resultado será el producto cartesiano entre las dos tablas. Vamos a ver un
ejemplo (muy sencillo porque el producto cartesiano produce resultados muy abultados):
SELECT Personas.Nombre, Coches.Marca FROM Personas, Coches
PersonaId Nombre CocheId
CocheId Marca
1
Benito
2
1
Ford
Focus
2
Pepe
2
2
Opel
Laguna
3
Lucía
3
3
Nissan
Almera
4
Andrés
1
4
Nissan
350z
Nombre
Marca
Benito
Ford
Benito
Opel
Benito
Nissan
Benito
Nissan
Pepe
Ford
Pepe
Opel
Pepe
Nissan
Pepe
Nissan
Lucía
Ford
Lucía
Opel
Lucía
Nissan
Lucía
Nissan
Andrés
Ford
Andrés
Opel
Andrés
Nissan
Andrés
Nissan
Modelo
Como vemos, al hacer el Join obtenemos el producto cartesiano de las dos tablas (es decir, cada fila de la
tabla A se combina con todas las de la tabla B por lo que al final acabamos teniendo n*m filas, donde n es
el número de filas de la tabla A y m el número de filas de la tabla b). Podemos ver como funciona el Join
observando que la marca Nissan aparece repetida, puesto que hay dos entradas de Nissan en la tabla
Coches estas dos entradas se combinan con las de la tabla personas y más tarde se filtran .
Aunque en unos pocos casos contados este ejemplo pudiera llegar a ser útil, en general el uso más
habitual de un Join es el de mezclar dos tablas para obtener resultados que pertenezcan a ambas tablas
Personas
Coches
Parking
. Esto, en realidad, ya lo vimos en el artículo anterior, aunque no le dimos nombre, voy a recuperar ese
ejemplo:
Facturas.*= FROM
Clientes
Clientes.Nombre
=Facturas,
'Pedro' AND
Facturas.IdCliente
Clientes.IdCliente
SELECT
WHERE
Que, como vimos, obtiene todas las facturas que pertenecen al cliente cuyo nombre es 'Pedro' (en
realidad, siendo puristas, obtiene todas las facturas que pertenecen a todos los clientes que se llaman
Pedro). Este es el caso más común de consulta Join y probablemente también el más útil, podemos
utilizar este tipo de consultas para obtener exactamente la información que necesitamos de entre dos
tablas.
La forma anterior de expresar un join es la forma implicita, es decir que el motor de la base de datos
internamente hará un Join para conseguirnos los resultados sin necesidad de que nosotros se lo
digamos. No obstante podemos conseguir el mismo resultado utilizando la declaración explicita del Join de
la siguiente forma:
Facturas.* FROM
Facturas INNER JOIN Clientes
Facturas.IdCliente
= Clientes.IdClient
SELECT
ON
Otro ejemplo, en una situación maestro detalle podemos hacer un join para obtener todas las direcciones
de cada cliente:
C.Nombre, =C.Apellido,
D.Direccion FROM Clientes C, Direcciones D
C.ClienteId
SELECT D.ClienteId
WHERE
de esta forma estaremos obteniendo el nombre, apellido y cada dirección para cada cliente que
conozcamos, produciría una salida similar a la siguiente (que como vemos repite nombres y apellidos por
cada dirección).
Nombre
Apellido
Direccion
Jorge
Martín
C/ Acacias 27
Jorge
Martín
C/ Castellana 102
Juan
Pérez
C/ Goya 134
Jose
Ruiz
Pº de las delicias 28
Outer Join
Un outer join es muy similar a un inner join exceptuando el trato que se da a aquellos registros que no
existen en una de las tablas. En un Inner Join tradicional cuando un elemento no existe en alguna de las
tablas ese elemento no se muestra en el listado final mientras que en el caso de un outer join si. Existen
tres tipos de outer join: left outer join, right outer join y full outer join. Los nombres, "left" (izquierda),
"right" (derecha) y "full" (completo) se refieren al comportamiento que queremos que tenga el join para
aquellos registros que no existen. Así, el left outer join mostrará siempre todos los registros de la tabla
izquierda (en la consulta) independientemente de que estén presentes en la tabla derecha, el right outer
join hará lo correspondiente con la tabla situada a la derecha mientras que el full outer join mostrará
todos los registros de las dos tablas. Vamos a ver algunos ejemplos comparando el inner join con el outer
join. Supongamos las tablas anteriormente vistas y una nueva que vendrá bien para los ejemplos
PersonaId Nombre CocheId ParkingId
CocheId Marca Modelo
Supongamos que realizamos un outer join entre la tabla personas y la tabla coches:
1
Benito
2
1
1
Ford
Focus
Pa
1
A4
Personas.Nombre,
Coches.Marca
Coches
Personas.CocheId
SELECT
FROM Personas
OUTER JOIN
2ON
Pepe
2 = Coches.CocheId
null
2 LEFT
Opel
Laguna
2
B3
3
3
A1
Lucía
3
7
3
Nissan
Almera
INNER JOIN
OUTER
JOIN
Producirá el siguiente resultado que es idéntico al de un inner join puesto que todos los registros de la
tabla izquierda poseen un valor presente en la tabla derecha:
Nombre
Marca
Benito
Opel
Pepe
Opel
Lucia
Nissan
Andrés
Ford
Sin embargo si realizamos un right outer join veremos como si hay diferencias
Personas.Nombre,
Coches.Marca FROM Personas RIGHT OUTER JOIN Coches
= Coches.CocheId
SELECT
ON Personas.CocheId
el resultado en este caso será:
Nombre
Marca
Benito
Opel
Pepe
Opel
Lucia
Nissan
Andrés
Ford
null
Citroen
que para el citroen tiene un null en la parte del nombre ya que no existe ninguna persona que tenga un
citroen. Otro ejemplo, si hacemos un inner join y un outer join entre la tabla Personas y la tabla Parking
Personas.Nombre,
Parking.Plaza
SELECT
Personas
FROM
Personas.ParkingID
= Parking.ParkingID
INNER JOIN Parking
ON
Nombre
Benito
Personas.Nombre,
Parking.Plaza
SELECT
Personas
Parking
FROM
Personas.ParkingID
Parking.ParkingID
RIGHT OUTER= JOIN
ON
Plaza
A4
Nombre
Benito
A4
null
B3
null
A1
null
A8
Plaza
Como vemos en el caso del outer join la tabla derecha (porque es un right outer join) se muestra
completa, con todos los registros independientemente de si estos están o no la tabla izquierda. Si
realizamos un left outer join obtendremos en cambio:
Personas.Nombre,
Parking.Plaza
Personas
Parking
SELECT
FROM
Personas.ParkingId
Parking.ParkingId
LEFT OUTER=JOIN
ON
Nombre
Marca
Benito
A4
Pepe
null
Lucia
null
Andrés
null
null
Citroen
Tags: Database [1] Sql [2] Tutorials [3] Submitted by Jorge on Thu, 01/29/2009 - 01:11
Source URL: http://www.thecoldsun.com/en/node/85
Links:
[1] http://www.thecoldsun.com/en/category/tags/bases-de-datos
[2] http://www.thecoldsun.com/en/category/tags/sql
[3] http://www.thecoldsun.com/en/category/content/tutoriales
Descargar