En la entrega anterior vimos una pequeña introducción al comando SELECT de SQL. En él vimos el uso más básico de este comando, es decir, su uso para realizar consultas sencillas de selección y obtener datos de una o varias tablas.
En un 90% de las situaciones ese será el tipo de consultas que utilicemos, sin embargo en ocasiones, ese 10% restante, necesitamos algo más preciso, un comando de selección que nos permita obtener justamente los datos que necesitamos y que no se refieren directamente a una tabla sino que son, quizá, suma de dos o más tablas, intersecciones, obtener los resultados agrupados, ordenados, etc... La sentencia SELECT nos permite hacer todo este tipo de cosas.
Como ya vimos en la introducción anterior la sintaxis general de una consulta de selección SELECT es la siguiente:
aunque una descripción más detallada es
Tabla1 y Tabla2 indican nombres de tablas de la base de datos. Para bases de datos basadas en esquemas (como por ejemplo Oracle) dicho nombre debe constituir el identificador completo, incluyendo el nombre del esquema, por ejemplo Gestion.Clientes.
La palabra clave DISTINCT nos permite indicar que deseamos filtrar los resultados repetidos, esto es, no devolver nunca dos filas exactamente iguales. Esta comparación se realiza entre dos filas completas es decir, para la siguiente tabla (que no esta en forma normal pero sirve para el ejemplo)
| Nombre | Facturacion | Mes |
|---|---|---|
| Manuel | 2300 | Enero |
| Zackarias | 3500 | Marzo |
| Sandra | 1900 | Marzo |
| Manuel | 2900 | Mayo |
| Sandra | 1900 | Junio |
Si realizamos la consulta
obtendremos
| Nombre |
|---|
| Manuel |
| Zackarias |
| Sandra |
mientras que si realizamos
obtendremos
| Nombre | Facturacion |
|---|---|
| Manuel | 2300 |
| Zackarias | 3500 |
| Sandra | 1900 |
| Manuel | 2900 |
en el que aparece Sandra una sola vez (puesto que conicide tanto el nombre como la facturación) mientras que Manuel aparece dos veces puesto que, aunque el nombre coincide, la facturación es distinta y por lo tanto se trata de dos filas diferentes.
La palabra clave AS permite asignar un alias a cada nombre de campo, es decir, asignarle un nombre más "legible" a un determinado campo de la base de datos que, por una razón o por otra, tiene un nombre poco adecuado.
Como podemos observar, de forma opcional podemos asignar un alias a cada tabla poniendo el nombre de dicho alias a continuación del nombre de la tabla. Todas la referencias a la tabla podrán entonces hacerse refiriendose al alias (t1.campo frente a Tabla1.campo). Lo mismo ocurre con los campos seleccionados a los que podremos asignar un nombre situandolo a continuación del nombre de dicho campo y precediendolo de la palabra reservada as como puede verse en la sentencia anterior.
En ocasiones al obtener datos de una tabla es posible que no deseemos limitar los campos (las columnas) que recibimos sino que queramos obtener todos y cada uno de los campos que componen la tabla podemos utilizar el simbolo *. Veamos un ejemplo:
Obtendría todos los campos correspondientes al cliente cuyo id es el 1.
Si queremos obtener todos los campos de una tabla pero solo algunos de una segunda:
Que obrendría todos los campos de la tabla Facturas pero solo el nombre de la tabla Clientes.
El primer lugar en el que comienza la complejidad de las clausulas de selección nos lo proporciona la clausula WHERE. En el paso anterior vimos algunos ejemplos básicos de su uso para obtener información de las tablas filtrando parte de la información. Vamos a adentrarnos un poco más ahora en su uso.
La clausula WHERE nos permite imponer condiciones o filtros en la selección indicada por la consulta. Expresado en un lenguaje coloquial nos permite decir: "de los datos que te he pedido, dame solo los que cumplan estas condiciones" y constituye la herramienta fundamental de casi toda sentencia SELECT.
Como ya vimos podemos escribir sentencias para obtener solo datos parciales de una tabla por ejemplo seleccionando todas las entradas de la tabla clientes cuyo nombre es "Pedro"
o bien utilizar la consulta para "mezclar" datos de varias tablas por ejemplo seleccionando todas las facturas pertenecientes a un cliente
La traducción literal de la sentencia anterior es: "dame todos los datos de la tabla facturas (facturas.*) cogiendo la tabla facturas y la tabla clientes en las que el nombre del cliente sea pedro y el id de la factura corresponda con el id del cliente". O dicho de otra forma, dame todas las facturas de todos los usuarios cuyo nombre sea pedro.
Para comprender mejor como funciona una clausula de selección WHERE podemos imaginarnos que la consulta se va ejecutando por pasos. Así en el caso anterior establecemos primero los resultados a aquellos clientes cuyo nombre es Pedro. Dichos clientes tendrán apellidos, dirección, etc y un identificador de cliente que es el que utilizamos en la segunda parte de la clausula diciendole, "ahora, de los anteriores, coge aquellas facturas cuyo id de cliente coincide.
Un 90% de las consultas SQL no necesitan nada más complicado que una clausula WHERE para limitar los parametros que buscamos en la base de datos.
Como ya hemos visto en algunos ejemplos, el comando de selección más común en una clausula WHERE son las comparaciones, y de hecho, dentro de ellas, la más común es la de igualdad, como veíamos en el ejemplo anterior:
Además de dicha comparación podemos utilizar cualquiera de los operadores de inigualdad como son mayor (>), menor (<), mayor o igual(>=), menor o igual (<=) y distinto (<>). Estos operadores pueden aplicarse tanto a campos de tipo número como a campos de tipo cadena. Para los primeros tienen el valor obvio de ordenación y para los segundos siguen el orden alfabético (en el caso <). Vamos a ver un par de ejemplos
Estaremos seleccionando todos aquellos clientes cuyo nombre no es Pedro.
Estaremos seleccionando todos aquellos clientes cuyo nombre es posterior (alfabéticamente) a Pedro, un ejemplo de salida podría ser:
| IdCliente | Nombre | Apellidos | Facturacion | Cliente_desde |
|---|---|---|---|---|
| 13 | Tony | Ramstein | 8000 | 1993 |
| 18 | Zackarias | Conner | 3500 | 2004 |
| 26 | Sara | García | 29000 | 1995 |
| IdCliente | Nombre | Apellidos | Facturacion | Cliente_desde |
|---|---|---|---|---|
| 10 | Manuel | Martínez | 2300 | 1999 |
| 15 | Zackarias | Conner | 3500 | 2004 |
| 16 | Sandra | González | 1900 | 1992 |
Estaremos seleccionando todos aquellos clientes cuya facturación sea inferior o igual a 5000 €, un ejemplo de salida podría ser:
Los operadores IN y BETWEEN nos permiten especificar rangos de valores válidos para los resultados de nuestra consulta, ya sea especificando una cota superior e inferior o un conjunto de valores.
El operador IN nos permite especificar un conjunto de valores, separados por comas, que serán considerados "válidos" para el campo especificado. Veamos un ejemplo:
Nos devolverá todos aquellos clientes que sean clientes nuestros desde 1995, 1997 o 1999
| IdCliente | Nombre | Apellidos | Facturacion | Cliente_desde |
|---|---|---|---|---|
| 10 | Manuel | Martínez | 2300 | 1999 |
| 26 | Sara | García | 29000 | 1995 |
Nos devolverá todos aquellos clientes que se llamen Pedro o Sara.
| IdCliente | Nombre | Apellidos | Facturacion | Cliente_desde |
|---|---|---|---|---|
| 1 | Pedro | Martín | 8500 | 2000 |
| 26 | Sara | García | 29000 | 1995 |
Por su lado el operador BETWEEN, que significa "entre" en inglés, nos permite especificar un limite inferior y superior para el valor deseado, por ejemplo:
Nos devolvería todos los clientes cuya facturación está entre 1400 y 5000 €.
El operador LIKE nos permite seleccionar todos aquellos valores que se aproximan a un patrón, es decir, nos permite realizar selecciones más avanzadas que se "parezcan" a un valor determinado. Podemos utilizar dos caracteres especiales con este operador:
De esta forma la sentencia 'm_ma%' indica cualquier cadena que empiece por "m" seguida de cualquier caracter, seguida de la secuancia "ma" seguida de cualquier cadena, así por ejemplo serían cadenas válidas "mama", "mamarracho" o "mimanos". Por ejemplo:
Que por ejemplo devolvería las entradas de Pedro y Medina
Que nos devuelve todos aquellos clientes cuyo nombre tiene exactamente 3 caracteres (hay tres '_') como por ejemplo Ana
Muy bien, ya tenemos los resultados que queremos, pero en algunos casos tendremos la necesidad de ordenar dichos resultados según algún criterio, como puede ser el nombre del cliente, el precio de la factura o cualquier otro tipo de criterio que se nos ocurra.
Para obtener un cierto orden en los registros se utiliza la clausula la clausula ORDER BY que funciona sencillamente especificando los campos por los que queremos ordenar el resultado. Por ejemplo, ampliando la consulta anterior:
o esta misma sentencia que es equivalente
Nos permite obtener las facturas de los clientes ordenadas por su precio, de menor a mayor. El orden por defecto de una ordenación es ascendiente, es decir, los valores "más pequeños" primero. Esto se aplica tanto numéricamente como alfabéticamente en función del tipo de campo sobre el que estemos tratando. En realidad existen dos especificaciones de orden, ASC y DESC. ASC es la función por defecto mientras que DESC ordena en sentido contrario, es decir, los "mayores" primero. De forma que si queremos rehacer la consulta anterior pero mostrando primero las facturas cuyo precio es mayor:
También podemos incluir más campos en el criterio de ordenación, en orden, es decir, primero se ordenará por el primero que pongamos y si hay dos o más valores iguales se ordenarán por el siguiente, etc. Por ejemplo:
que nos mostrará primero las facturas cuyo precio sea menor y, si dos facturas tienen el mismo precio, primero aquellas cuyo número de items sea menor. Si quisieramos, por ejemplo, que se mostraran primero las facturas cuyo precio es mayor y, si hay dos con el mismo precio, aquellas cuyo numero de items es menor