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