Select

(Mi agradecimiento a Alejandro Estraviz, porque este texto es suyo)

Select o como recuperar información de una manera sencilla.
Con el auge las bases de datos actuales, es casi necesario el uso de un lenguaje específico para recuperar información, la solución: SQL.

Un poco de historia
En un principio el tratamiento de los datos se realizaba a través de ficheros, bien de texto plano, bien con formato. Por supuesto, y como podemos intuir hoy en día, era una forma rudimentaria de tratar los datos, aunque en aquella época era lo que había.
Entre los problemas más importantes que surgían caben destacar:
– Redundancia e inconsistencia de datos: probablemente más de un fichero guardase los mismos datos, lo que hacía casi imposible tenerlos actualizados.
– No permitían los accesos concurrentes: en el momento en que un usuario utilizaba una « base » (un fichero en realidad) el S.O. lo bloqueaba, de manera que sólo él podía acceder a los datos.
– Seguridad: al tratarse de ficheros puros y duros, cualquier persona que accediese al sistema podía acceder a ellos y manipularlos.
Para poder solucionar estos problemas surgieron los sistemas de gestión de bases de datos (SGBD a partir de ahora) que cubrían todas esas deficiencias llevando a cabo una gestión completa de los datos guardados, tanto de una manera lógica como física. La idea era que cualquier persona, sin necesidad de ser informática, pudiese manejar medianamente bien una base de datos. Era necesario escapar de los lenguajes convencionales. Se necesitaba un lenguaje que no utilizase algoritmos. Para ello surge el lenguaje SQL (Standard Query Language) que mediante preguntas podía recuperar la información de la base de datos. No era necesario crear complejos algoritmos que recorriesen las tablas, simplemente generábamos una consulta y ésta nos devolvía la información que necesitábamos.

La sentecia estrella: select
Dentro del lenguaje SQL no cabe la menor duda de que si tenemos que hablar de una sentencia, el premio se lo lleva la orden select, entre todas las que implementa SQL: create, delete, update, etc… el 90% de las ocasiones en que necesitamos utilizar este lenguaje lo hacemos a través de su sentencia talismán. Esto viene condicionado por la gran variedad de opciones que ofrece, además de la gran potencia que es capaz de desarrollar a la hora de realizar búsquedas avanzadas. Se puede asegurar que si tenemos la estructura de la base bien creada, a través de SQL podremos extraer cualquier tipo de información por muy rebuscada que ésta sea. Tan sólo dependerá de nuestra pericia y de un poco de tiempo para implementar y ejecutar la consulta.
Aunque a primera vista pueda parecer el uso de esta orden una panacea, no lo es. Para poder sacarle todo el jugo, hemos de conocer bien su forma, así como las opciones y variaciones que ofrece; hemos de tener en cuenta que cuando ejecutamos una consulta sólo observamos el resultado, pero en caso de que no funcione adecuadamente, no sabremos porqué no ha funcionado, ni tendremos un mensaje de error al estilo de los lenguajes actuales, que nos indique porqué no nos devuelve la información que queríamos. Por supuesto si estructuramos mal la sentencia o cometemos algún tipo de error sintáctico o léxico el compilador nos mostrará un mensaje.
Estructura de la sentencia
Si es importante conocer las posibilidades que nos ofrece esta sentencia, más importante es dominar su estructura y las opciones que proporciona. Básicamente la estructura de una sentencia select viene a ser la siguiente:

Select {columna1, columna2,…}
From {tabla1,tabla2,…}
{Where predicado}
{order by columna1, columna2,…}

Las partes fundamentales son las dos primeras. En ellas primero especificamos lo que queremos recuperar, las columnas de la tabla o tablas que nos interesan. Un defecto muy grave es el hecho de utilizar el ‘*’ en vez de enumerar los nombres de las columnas que queremos. De esta manera nos evitamos teclear más. Pero si el día de mañana la estructura de la tabla cambia, deberemos modificar nuestro programa, pues recibirá datos para los que no está preparado. Por ello es prácticamente un error el hecho de utilizar ‘*’ en un select. En una segunda línea especificamos de dónde queremos recuperar esas columnas. En caso de utilizar varias tablas, podemos anteponer un alias para referirnos más tarde a ellas en la misma sentencia.
El resto son opciones, quizás la más importante es la primera de ellas en la cual, a través de un predicado, seleccionamos los registros que queremos recuperar. El predicado puede ser cualquier expresión evaluable utilizando operadores relacionales, además de palabras clave como LIKE –que nos permite seleccionar algo « parecido a »– o IN, que nos permite elegir un conjunto dentro del cual queremos que estén los valores devueltos. En el recuadro adjunto se pueden observar mejor las opciones de los predicados. Por supuesto aparte de la inclusión de cualquier tipo de predicado de los descritos, estos pueden agruparse y relacionarse con los conectores lógicos and y or. De esta manera la potencia de selección se ve aumentada.
Al realizar la búsqueda podemos querer que los datos resultantes vengan ordenados por alguna de sus columnas. Para lo cual contamos con la cláusula order by que, introducida al final de la sentencia, genera un orden en el conjunto de registros solución. Con la cláusula desc el orden se hará en forma descendente.
Otro de los problemas que resuelven las opciones de la sentencia select es el hecho de querer conseguir únicamente los elementos distintos de los registros resultados. Por ejemplo, si sólo nos interesa saber qué cantidades cobran nuestros empleados; pero no lo que cobra cada uno, sino los diferentes sueldos que pueden tener –bien para crear una escala o bien para simplemente ver entre qué valores se mueven– tenemos dos opciones: si lo ejecutásemos de una forma normal, tendríamos un listado interminable con los, por ejemplo 100.000 empleados que tenemos. Sin embargo, usando la cláusula distinct a la hora de nombrar la columna elegida, obtendríamos los distintos sueldos de nuestros empleados, que de ser más o menos uniformes, no contendría más de 20 o 30 registros.
Trabajar con más de una tabla
Hasta ahora sólo habíamos trabajado con una tabla. Pero normalmente el uso que le daremos a la orden select es la de relacionar varias para proporcionar información nueva. Para conseguirlo, dentro de la estructura podemos indicarle al sistema que queremos usar distintas tablas:

Select apellido, sueldo, localidad
From emp,dept
Where emp.apellido=’Lopez’
And dept.nombre=’Ventas’;

De esta manera le estamos indicando al gestor que queremos los apellidos, el sueldo y la localidad de los empleados del departamento de ventas, cuyo apellido sea López. Por supuesto podemos incluir condiciones que agrupen las tablas por un campo, algo muy utilizado en el desarrollo del modelo relacional (Modelo E-R):

Select nombre, sueldo
From emp, dept
Whete emp.dept_no=dept.dept_no;

Con este código conseguimos un listado de los nombres (incluidos dentro de la tabla emp) y los sueldos (incluidos en la tabla dept) de todos los empleados de la empresa, correspondiendo cada sueldo al empleado correcto.
Select permite también la generación de resultado aritméticos. Por ejemplo en caso de tener una tabla con sueldo y otra con comisión, podríamos listar el nombre de los empleados junto con la suma de ganancias recibidas, suponiendo que tenemos el salario en una tabla y las comisiones en otra:

Select nombre, apellidos, sal+comision
From emp, dept
Where emp.dept_no=dept.dept_no;

Dentro de las capacidades aritméticas también podemos calcular la suma de una columna, cláusula sum, la media aritmética avg, el máximo valor max, el mínimo valor min, y la cantidad de registros que obtendríamos count. Todos estas opciones se incluirían dentro de la sentencia anteponiéndose a la columna a la que van a modificar:

Select max(salario), min(salario), avg(salario), count(salario)
From emp;

Así conseguiríamos los datos estadísticos de los salarios de los empleados de nuestra empresa. Un dato a tener en cuenta es que no podemos mezclar resultados globales con resultados individuales, es decir, no podríamos listar los nombres de los empleados junto con la suma de sus salarios. Sí podríamos listar la suma de los sueldos de cada departamento de la empresa; pues dentro de cada departamento tenemos distintos empleados. El agrupamiento de los datos puede hacerse también con la cláusula group by, sin necesidad de utilizar operadores aritméticos.
De manera análoga a como especificábamos las características que deberían tener los registros resultantes de una búsqueda con where, cuando utilizamos el agrupamiento de datos podemos indicarlo con la orden having. Esta cláusula actúa sobre los grupos creados. Es decir, produce un filtrado después del agrupamiento de los datos, y elimina grupos completos, no trabaja sobre las tuplas individuales.
Un ejemplo podría ser el siguiente:

Select nombre, oficio, sum(salario), count(*), avg(salario)
From emp, dept
Where emp.dept_no = dept.dept_no
Group by nombre, oficio
Having count(*) >= 2;

Con esta orden conseguiríamos un listado con el número de empleados que hay en cada puesto de la empresa, junto con la suma y la media de sus sueldos para cada puesto, de cada departamento. Siempre y cuando ese departamento tenga más de un empleado, una salida típica sería la siguiente:

Nombre Oficio Sum(salario) Count(*) Avg(salario)
===================================================
Investigación Analista 780000 2 390000
Investigación Empleado 247000 2 123500
Ventas Vendedor 723000 4 180750

Sentencias anidadas
La potencia de la orden select también se encuentra en la posibilidad de anidar sentencias unas dentro de otras. Por ejemplo si queremos obtener un listado con los valores de una determinada columna dentro de los valores que tiene otra columna de una tabla diferente, podríamos crear una subconsulta que consiguiese esos valores para luego compararlos con los datos de la primera. Volviendo al ejemplo de los empleados, podríamos querer saber los empleados que tienen el mismo empleo que el empleado López:

Select apellidos, oficio
From emp
Where oficio =
( Select oficio
From emp
Where apellidos=’Lopez’);

Todos los SGBD ante una sentencia anidada comienzan desarrollando la búsqueda interna, es decir van de dentro hacia fuera. De esa forma pueden ir resolviendo las cláusulas where que engloban a la sentencia select desarrollada.
El uso de sentencias anidadas produce una carga en la máquina considerable, puesto que para cada registro ha de realizar una búsqueda completa para la orden anidada. Por eso se debe tener mucho cuidado con el uso que se hace de estas estructuras. En una máquina que deba responder en tiempos muy cortos en un entorno multiusuario la ejecución de una orden de este tipo podría reducir el rendimiento del sistema de una forma notable. Como es obvio, utilizar anidamientos de orden mayor incrementa exponencialmente la carga para la máquina.

Conclusiones
La utilización del lenguaje SQL ha llegado a ser hoy en día prácticamente indispensable. Con el gran crecimiento de las bases de datos actuales, hablamos ya de gigas como quien hablaba hace años de kbytes. El uso de una forma rápida, flexible e independiente de la solución software escogida es algo fundamental. Es precisamente lo que nos ofrece SQL. Con él podemos crear programas que accedan de una manera eficiente a cualquier tipo de base, creando listados e informes de distintos tipos de información, con la única barrera de nuestra pericia para crear consultas.
De entre todas las órdenes que incorpora SQL, la sentencia select es, como hemos visto en este artículo, la estrella. Gracias a su variedad de opciones y cláusulas podemos modelar la información de la manera que más nos interese. Podemos extraer todo el conocimiento que esconde nuestra base de datos. Podemos crear listados del más variado tipo. Podemos, en resumen, sacarle todo el partido a nuestros datos.
Por supuesto, se pueden crear consultas de lo más complicado, consultas difíciles de entender –aun conociendo el tema y dominándolo– pero no hay que preocuparse. En la vida cotidiana estas consultas rara vez son necesarias, y ver sentencias con tres o cuatro anidamientos a la vez que con distintos agrupamientos es casi imposible. No obstante, siempre viene bien practicar con este tipo de consultas para poder comprender con un vistazo cualquiera de ellas que se nos presente.
Para más datos sobre SQL y la sentencia select, podéis consultar cualquier manual de SQL, o bien utilizar alguno de los específicos para algún SGBD, como el « Manual de refencia de Oracle » o el « SQLPlus User’s Guide And Reference ».