El lenguaje SQL (Structured Query Language) o lenguaje de consulta estructurado, es el principal medio de consulta sobre bases de datos que se utiliza en la actualidad. Sus capacidades lo hacen óptimo para la consulta no planificada o improvisada de bases de datos, sin necesidad de recurrir a la programación de informes que no se utilizarán más que en contadas ocasiones. En principio fue diseñado para ser un lenguaje muy parecido al natural, de hecho si usted conoce el idioma ingles, el significado de las consultas se le hará más familiar. En todo caso la exposición que viene a continuación está dirigida a un usuario no informático y con poca experiencia.
Como ejemplo introductorio fíjese en la siguiente frase en castellano:
“Selecciona el nombre y la edad de los clientes que sean mayores de 68 años”
Es una orden comprensible para todos nosotros, ahora sustituyamos algunas palabras por su traducción al idioma ingles y al lenguaje lógico. Cambiaremos “Selecciona” por “Select”, “de los clientes” por “From clientes”, “ que sean” por “Where” y “mayores de 68 años” por “Edad>68”. El resultado sería “Select nombre, edad from clientes where edad>68”, que resulta ser una sentencia de consulta válida en SQL y que obtiene los datos requeridos por la frase en castellano.
Es importante tener claro el significado de los conceptos que vienen a continuación para poder operar con el lenguaje de consulta SQL. Ya que una expresión de consulta SQL es siempre dependiente de la estructura de datos que subyace a nuestro sistema informático en cuestión.
Base de datos: Una base de datos es un depósito físico de información compuesta por unas estructuras de almacenamiento más simples que llamaremos “tablas”.
Tabla: Una tabla es a efectos prácticos un conjunto de “registros” con el mismo formato, que guardan información referente por ejemplo a personas, facturas, Inmuebles, Recibos, pagos etc. Cada tabla se relaciona por tanto con una entidad del mundo real sobre la que se pretende guardar información.
Registro: Un registro es una agrupación de “campos” que describen por ejemplo a una persona, factura, recibo, pago etc. Un registro describe a un individuo representante de esa entidad del mundo real que citábamos en la definición anterior.
Campo: Viene siendo la unidad de información más pequeña de una base de datos, por ejemplo la edad o el nombre de un cliente, la fecha de vencimiento de una letra etc. Un campo es por tanto una característica de cada individuo u objeto del mundo real.
Ej: Una base de datos estaría compuesta de las tablas denominadas Factura, Cliente, Inmueble etc. Un registro por ejemplo de la tabla cliente agrupa los campos de Nombre, Nif, Edad, Estado civil con sus correspondientes valores etc. Esta forma de organizar la información resulta ventajosa para la realización de sistemas informáticos con corrección y con capacidad para obtener y relacionar la información.
Consulta: Es una expresión (frase) en un lenguaje determinado que recupera datos de una base de datos. Está compuesta de referencias a campos y tablas e incorpora “restricciones” para acotar o discriminar la información que queremos obtener.
Restricción (o condición): es una expresión lógica del tipo “campo operador valor”, que acota o restringe los datos a recuperar por la consulta. Ej: Nombre=”Miguel”. Indica que el campo Nombre debe de contener el valor Miguel para cumplir la restricció n. Intérprete: Se llama así al programa informático que analiza nuestras sentencias de consulta SQL las evalua y recupera los registros que deseábamos obtener con dicha consulta.
Una sentencia de consulta Sql se compone de la palabra “SELECT” en primer lugar, que indica al programa interprete de la consulta, que lo que queremos es recuperar datos de la base de datos. En ingles “SELECT” significa “seleccionar”. A continuación indicamos la lista de “campos” que queremos obtener, que serán las columnas de nuestro informe. A continuación indicaremos la lista de tablas de donde proceden dichos campos precedido de la palabra inglesa “FROM” que significa “de”. Y por últi mo indicaremos las restricciones que limiten la información a obtener, precedidas de la palabra “WHERE” que significa “donde”.
Ej: Tenemos una base de datos que entre otras se compone de la “tabla” de Clientes. Los registros de dicha tabla se componen de los campos Nombre, nif, edad, estado_civil. Queremos saber que clientes tienen una edad comprendida entre los 20 y los 35 años. La sentencia de consulta sería la siguiente:
SELECT NOMBRE, NIF, EDAD, ESTADO_CIVIL FROM CLIENTES WHERE EDAD>=20 AND EDAD<=35
Nótese que después de SELECT estamos especificando la lista de todos los campos de la tabla Clientes, en realidad podríamos haber escrito simplemente un asterisco para indicar que queremos recuperar todos los campos de la tabla (SELECT * FROM......) o bien solo aquellos campos que quisiésemos recuperar (SELECT NOMBRE, NIF FROM.......).
Nótese ademas que la restricción es compuesta, es decir esta formada a partir de otras más pequeñas separadas por la conjunción lógica AND. Esta conjunción indica que los registros que se recuperen han de cumplir todas las restricciones que separa la palabra AND.
Esto se ve más claro traduciendo la consulta al español:
SELECCIONA EL NOMBRE, LA EDAD, EL ESTADO CIVIL DE LOS CLIENTES CUYA EDAD SEA MENOR QUE 35 Y MAYOR QUE 20.
El “Y” de esta frase hace la misma función que el “AND” de la consulta SQL.
La contrapartida del “AND” sería “OR” que en castellano equivaldría a la disyunción o. Ej: SELECT * FROM CLIENTES WHERE NOMBRE=”MIGUEL” OR NOMBRE = “JUAN” La anterior consulta seleccionaría aquellos clientes cuyo nombre fuese Miguel o bien Juan.
Las restricciones del ejemplo anterior son sencillas. Se pueden elaborar restricciones más complejas combinando los diferentes operadores disponibles.
Ejemplos: EDAD>17 Mayor de edad.
NOMBRE=”MIGUEL” Nombre igual a miguel. (los valores alfabéticos y las fechas se ponen entre comillas simples o dobles)
FECHA_OPERACION=FECHA_DEFUNCION En esta restricción estamos comparando dos campos de la misma tabla, por ejemplo pacientes. Obtendríamos aquellos pacientes muertos el día de su operación.
FECHA_DEFUNCION IS NULL Con esta restricción obtendríamos los pacientes que estan vivos. Las palabras IS NULL Indican que el valor del campo es nulo, o sea que el campo no ha sido rellenado. El valor NULL requiere una serie de consideraciones que comentaremos más adelante.
ESTADO_CIVIL=”S” Estado civil soltero suponiendo que este estado se almacenase con el valor S.
ESTADO_CIVIL<>”C” Estado civil distinto de casado suponiendo que este estado se almacenase con el valor C.
FECHA_VENCIMIENTO BETWEEN ‘1/23/1998’ AND ‘1/25/1998’ Fecha de vencimiento comprendida entre el 23 de Enero de 1998 y el 25 de Enero de 1998 incluidos. Nótese que las fechas se expresan en formato anglosajón. BETWEEN significa entre. Se podría construir la misma restricción con los operadores >= y <= de la siguiente forma FECHA >= valor AND FECHA<= valor, sin embargo estamos empleando dos operadores y arriba solo empleamos uno.
CODIGO IN (1,2,3,7,88) Estamos indicando que el valor del campo código debe de estar incluido en la lista de valores de código que figura entre paréntesis separados por comas.
APELLIDO LIKE “%EZ” El operador LIKE combinado con el comodín% que cumple una función similar al * en MS-DOS sustituyendo a un número indeterminado de caracteres. Permite la comparación con patrones alfabéticos, LIKE significa como.
En la restricción de ejemplo estamos pidiendo que el apellido termine en EZ, o sea
RODRÍGUEZ, GONZÁLEZ etc.
Un ejemplo de sentencia SQL de consulta combinando los operadores anteriores sería:
SELECT SALARIO_BRUTO, SALARIO_BRUTO - (SALARIO_BRUTO*RETENCION)
FROM CLIENTES WHERE APELLIDO LIKE “Ro%” AND EDAD BETWEEN 30 AND 45 AND ESTADO_CIVIL <>’C’ AND SALARIO>300000 Obtendríamos el salario bruto y el neto a aquellos clientes cuyo apellido comienza por “Ro” y cuya edad esta comprendida entre los 30 y los 45 años que no estan casados y cuyo salario supera las 300.000 pesetas.
Las restricciones complejas se elaboran a partir de las simples, utilizando los operadores o conectivas lógicas AND y OR citados anteriormente. También utilizaremos el operador NOT cuando queramos que una condición sea negativa o sea que no se cumpla. Cuando queramos combinar conjunciones con disyunciones, o sea restricciones separadas por AND y OR indistintamente es recomendable el uso de paréntesis para indicar al programa interprete de SQL que condiciones van juntas y cuales no.En caso contrario el interprete concede prioridad a las condiciones separadas por AND, o sea evalua primero las restricciones separadas por AND. Si utilizamos paréntesis de un modo similar al que hacemos cuando escribimos una expresión aritmética en una calculadora, las restricciones compuestas resultan mucho más comprensibles. Aclararemos todo lo anterior con una serie de ejemplos comentados.
- SELECT * FROM LETRAS WHERE NOT FECHA_VENCIMIENTO>’1/1/1998’
Estamos empleando el operador lógico NOT.El significado de la consulta es seleccionar todos los campos de las letras cuya fecha de vencimiento no sea posterior al 1 de Enero de 1998. Podríamos haber empleado el operador <= sin el NOT para obtener el mismo resultado.
- SELECT * FROM LETRAS WHERE (FECHA_VENCIMIENTO>=’1/1/1998’ AND FECHA_VENCIMIENTO<=’1/2/1998’) OR FECHA_LIBRAMIENTO=’1/1/1998’
Aquí tenemos un ejemplo de utilización combinada de AND y OR utilizando paréntesis. El significado de esta consulta es, seleccionar todos los campos de los registros de la tabla “letras” cuya fecha de vencimiento este comprendida entre el 1 y 2 de enero del 98 o bien aquellas letras cuya fecha de libramiento sea el 1 de Enero del 98. En este caso el intérprete evalua primero las restricciones separadas por el AND, si ambas se cumplen ya no necesitaría evaluar la condición que va despues del OR puesto que al cumplirse lo que va antes que el OR hace cierta a toda la expresión que va despues de WHERE. Lo mismo ocurriría si fuese cierta la condición que va después de OR, si es cierta hace cierta a toda la expresión de restricción que va despues de WHERE a pesar de que no se cumpliesen las restricciones simples referentes a la fecha de vencimiento.
- SELECT * FROM PACIENTES WHERE (FECHA_DEFUNCION IS NULL OR FECHA_OPERACIÓN IS NULL) AND NOT (NOMBRE=’JUAN’ OR NOMBRE LIKE ‘JOS%’)
Aquí tenemos una consulta un poco más complicada y que resulta más difícil de interpretar a primera vista. Su significado es seleccionar todos los campos de la tabla de pacientes y se ha de cumplir obligatoriamente que o bien no han fallecido o no se han operado, y también se ha de cumplir obligatoriamente que no sea cierto que el cliente se llame JUAN o que su nombre empiece por JOS. Veamos como evaluaría el intérprete el cumplimiento de estas condiciones por parte de los registros de la tabla de pacientes. En primer lugar evaluaría las restricciones compuestas que van entre paréntesis. Empezamos con la primera y vemos que un registro cumple esta condición para ser seleccionado cuando cualquiera de las dos fechas FECHA_DEFUNCION o FECHA_OPERACIÖN tienen un valor nulo. Si esto se cumple, pasaría a evaluar la restricción que va después del AND o sea NOT (NOMBRE=’JUAN’ OR NOMBRE LIKE ‘JOS%’) y veremos si los registros cumplen que el nombre del paciento ni es JUAN ni comienza por JOS. Si esta segunda restricción compuesta se cumple también, entonces el registro es seleccionado. Notese que la restricción NOT (NOMBRE=’JUAN’ OR NOMBRE LIKE ‘JOS%’) como usted mismo puede comprobar equivaldría a la siguiente expresión de restricción: NOT NOMBRE=’JUAN’ AND NOT NOMBRE LIKE ‘JOS%’ Esto es porque expresado de un modo formal, la negación de una disyunción equivale a la conjunción de negaciones. Y como contrapartida la negación de una conjunción equivale a la disyunción de negaciones.
Como habrá podido observar la capacidad para restringir o discriminar los datos que queremos obtener con una consulta SQL es extremadamente amplia y flexible. Hasta el momento solo hemos visto las consultas que trabajan a nivel de una sola tabla o sea estamos consultado información referente a una sola entidad del mundo real (clientes, letras o facturas) con independencia de las demás que se relacionan en nuestra base de datos. Es decir no sabemos todavía como relacionar un cliente con sus facturas o un paciente con su médico. En el siguiente punto trataremos las consultas que asocian o relacionan a las distintas entidades descritas en forma de tablas en nuestra base de datos.
¿ COMO CONSULTAR SOBRE VARIAS TABLAS RELACIONADAS?
Decíamos al principio que una base de datos esta compuesta de tablas que guardan información sobre varias entidades del mundo real . Es muy común que estas entidades del mundo real guarden relación entre sí, relaciones que interesa reflejar a la hora de obtener informes mediante sentencias de consulta SQL. Por ejemplo los médicos con sus pacientes, los inquilinos con los inmuebles que habitan relacionándolo a su vez con los propietarios de dichos inmuebles. Para saber como relacionar dos tablas entre sí, es necesario definir dos conceptos sencillos previamente, el concepto de clave de registro y clave de referencia. Una clave de registro es un conjunto de uno o más campos que identifican a ese registro y lo distinguen de todos los demás que componen la tabla, por ejemplo la clave del registro que describe a una persona podría ser el Nif si este no se repitiese para ninguna otra persona, la clave del registro que describe a un automóvil podría ser su matrícula. Una clave de referencia es un conjunto de uno o varios campos de un registro cuyo valor o valores hacen referencia a la clave de registro de otra tabla. Este es el mecanismo por el cual podemos relacionar registros individuales en diferentes tablas. Por ejemplo tenemos una tabla de automóviles y otra de propietarios, y queremos reflejar la relación de pertenencia de cada automóvil o automóviles con sus propietarios suponiendo que cada vehículo solo pertenece a una persona. Supongamos que la clave de registro del propietario es su Nif, entonces el registro que describe a cada vehículo que le pertenezca debe contener un campo llamado por ejemplo “Nif_Propietario” cuyo valor sea precisamente el Nif del propietario. De esta forma automóviles y propietarios quedan asociados.
Veamos ahora, sobre este mismo ejemplo, como podríamos obtener mediante una consulta SQL los vehículos que pertenecen a un cliente determinado, por ejemplo aquellos que pertenecen al cliente de nif “32770762V”.
SELECT A.* FROM AUTOMOVIL A, PROPIETARIO P WHERE P.NIF=”32770762V” AND A.NIF_PROPIETARIO=P.NIF
Esta consulta requiere múltiples aclaraciones.
En primer lugar estamos renombrando las tablas con “alias”, un alias es un nombre temporal que se usa dentro de la consulta para simplificar o acortar el nombre real de las tablas en las múltiples referencias que se haga a dichas tablas. En este caso usamos el alias A para automóvil y P para propietario, pero puede usted elegir los nombres de alias que desee. Los “alias” sirven también para aclarar, en el caso de que las tablas posean campos con el mismo nombre, a cual estamos haciendo referencia realmente. Por ejemplo sí la tabla Automóvil tuviese un campo llamado “Código” y la de propietarios un campo llamado “Código”, haríamos referencia al de propietario como P.CODIGO y a la de automóvil como A.CODIGO. Nótese igualmente que hemos escrito SELECT A.* para que muestre solo los campos pertenecientes a la tabla automóvil. Si hubiésemos escrito solo * obtendríamos todos los campos de las dos tablas en cada línea resultante del informe.
Aclararemos ahora la restricción P.NIF=”32770762V” AND A.NIF_PROPIETARIO = P.NIF. La condición que precede a AND limita los propietarios a aquellos que tengan el Nif 32770762V, que sí cumple la condición de clave de registro que citamos anteriormente estaremos trabajando con un solo propietario. La segunda restricción, la que va después del AND, es la que indica al interprete de SQL como relacionar a los automóviles con sus propietarios, le estamos exigiendo que el valor de la clave de referencia de la tabla automóvil sea el mismo que la clave de registro de la tabla propietario. Esto unido a la primera de las condiciones nos llevará a obtener los datos de los automóviles del propietario cuyo nif es 32770762V.
Si la consulta fuese SELECT * FROM AUTOMOVIL A, PROPIETARIO P WHERE A.NIF_PROPIETARIO=P.NIF estaríamos pidiéndole al intérprete que nos mostrase todos los automóviles relacionados con sus propietarios. Y aparecerían todos los datos del propietario junto a los de su automóvil, en la misma línea del informe.
Sin embargo supongamos ahora la siguiente consulta:
SELECT * FROM AUTOMOVIL, PROPIETARIO
Según el lenguaje SQL estándar es una sentencia correcta, pero en realidad sus resultados son poco útiles además de producir un retardo grande en la resolución de la consulta si el número de registros en ambas tablas es elevado.
En realidad lo que estamos obteniendo con esta consulta es la combinación de todos los automóviles con todos los propietarios independientemente de sí son suyos o no. Si tuviésemos 5.000 vehículos y 4.000 propietarios obtendríamos 20.000.000 de líneas de informe combinando cada vehículo con todos los propietarios. Le recomendamos que no realice nunca esta operación que además de costosa, tan solo tiene un significado teórico dentro del mundo de las bases de datos.
¿ COMO RELACIONAR MÁS DE DOS TABLAS?
Explicaremos este caso con una ampliación del ejemplo anterior. Supongamos ahora que además de los propietarios y los automóviles, existe otra entidad en nuestra base de datos que se relaciona con los propietarios y a través de estos con los vehículos, esta entidad podría ser la empresa donde trabaja el propietario. O sea cada empresa tendrá varios empleados que son propietarios de automóviles. Supongamos que la clave de registro de la empresa es su CIF y que cambiamos el nif de cada propietario por un número de serie progresivo (del tipo 1,2,3....,N) que cada empresa asigna a sus empleados cuando se van incorporando a la empresa. En estas circunstancias y en ausencia del Nif de los propietarios, no nos basta con el número de serie del empleado para que actúe como clave de registro puesto que puede coincidir entre empleados de diferentes empresas, por tanto usaremos como clave del registro de propietario la combinación de los campos “número de serie” del empleado (Numero_serie), y un campo llamado “Cif_Empresa” que actúa además como clave de referencia a los registros de la tabla empresa. En resumen tenemos las siguientes tablas con sus campos:
Empresa (Cif, Razon_social, Tfno......etc) Propietario (Cif_empresa, Numero_serie, Nombre, Tfno, Domicilio.....etc) Automovil (Matricula, Cif_empresa, Numero_serie_Propietario, Cilindrada,.. etc)
Nótese que la clave de referencia del automóvil con respecto al propietario ha cambiado para ser congruente con la nueva estructura de la tabla de propietarios y poder referenciarla. Ahora esta compuesta por Cif_empresa y Numero_serie_Propietario que referencia a los campos Cif_empresa y Numero_serie de la tabla propietario respectivamente.
Escribimos ahora una consulta que obtendrá para una determinada empresa de Cif A22334455 las matrículas de los automóviles de sus empleados con su nombre. Vemos que en esta consulta queremos relacionar información de las tres tablas.
SELECT A.MATRICULA, P.NOMBRE FROM AUTOMOVIL A, PROPIETARIO P, EMPRESA E WHERE E.CIF=’A22334455’ AND P.CIF_EMPRESA = E.CIF AND A.CIF_EMPRESA = P.CIF_EMPRESA AND A.NUMERO_SERIE_PROPIETARIO = P.NUMERO_SERIE
En esta consulta con la primera restricción estamos seleccionando solo aquellos registros de la tabla de empresas con el cif A22334455, con la segunda restricción estamos restringiendo los propietarios seleccionados a aquellos que pertenecen a la empresa citada, puesto que obligamos a que la clave de referencia del propietario respecto a la empresa sea igual a la clave propia del registro de la empresa. Las dos últimas restricciones obligan a que la clave de referencia del automóvil con respecto al propietario sea igual a la clave propia del registro de propietario con lo cual estamos obteniendo solo aquellos automóviles que pertenecen a propietarios que trabajan en la citada empresa. Es importante entender cual sería el resultado de esta consulta. Por ejemplo, si el empleado con número de serie 1, de la empresa de Cif A22334455, que se llama “Pedro Jiménez”, tuviese dos coches de matrículas “C -4545- BV” y “C -5454- BV” respectivamente, en el informe resultante de la ejecución de la consulta aparecería:
MATRICULA NOMBRE ............................................. C-4545-BV Pedro Jiménez C-5454-BV Pedro Jiménez ............................................. .............................................
O sea aparece una línea por cada automóvil que pertenezca a un propietario que trabaja en la citada empresa. Si en la misma consulta anterior seleccionásemos solo el campo Nombre el resultado de la consulta SELECT P.NOMBRE FROM.......etc. sería el siguiente: NOMBRE Pedro Jiménez Pedro Jiménez
El nombre aparecería 2 veces a pesar de que solo queremos saber los nombres de los empleados que tienen coche en la empresa de Cif A22334455. Para solucionar este problema existe el operador DISTINCT que en ingles significa “distintos”. La consulta para obtener los distintos nombres de los propietarios de automóviles que trabajan en la empresa A22334455 sería: SELECT DISTINCT P.NOMBRE FROM AUTOMOVIL A, PROPIETARIO P, EMPRESA E WHERE E.CIF=’A22334455’ AND P.CIF_EMPRESA = E.CIF AND A.CIF_EMPRESA = P.CIF_EMPRESA AND A.NUMERO_SERIE_PROPIETARIO = P.NUMERO_SERIE
Nótese que así estamos obteniendo la lista de propietarios que realmente tienen un vehículo en nuestra base de datos. Aclaremos esto, sí para el propietario con número de serie 2 de la empresa con cif A22334455 no existe en la tabla de automóviles ningún registro referenciando a este propietario, el nombre de dicho propietario no saldría en el resultado de la consulta anterior.
En resumen para poder obtener consultas relacionando múltiples tablas entre si ha de conocer bien cuales son las claves propias de registro y las claves de referencia de unas tablas con respecto a otras. Por tanto antes de ponerse a hacer este tipo de consultas consulte un esquema detallado de la base de datos, que se suministra con cada programa. Por último y como dato anecdótico decir que el tipo de consulta que hemos estado describiendo se denomina en términos informáticos JOIN que significa “Asociar”. Existen ot ras formas de expresar estas consultas utilizando precisamente la palabra JOIN, pero no lo describiremos en este manual puesto que interpretamos que la sintaxis descrita es más intuitiva.
¿ COMO CONSULTAR CON SUMAS, MEDIAS Y CUENTA DE REGISTROS SELECCIONADOS?
Si a los campos seleccionados en una consulta le aplicamos una serie de funciones de cálculo disponibles en SQL (SUM, AVG, COUNT que significa suma, media y cuenta) podremos obtener resultados de cálculos aplicados a todos los registros de nuestra consulta. Por ejemplo queremos obtener el salario medio de los empleados de nuestra empresa.
SELECT AVG(SALARIO) FROM EMPLEADOS El resultado sería una sola linea en el informe con el salario medio de nuestros empleados.
Ahora queremos saber cual es el salario medio de los empleados con categoría de directivo. SELECT AVG(SALARIO) FROM EMPLEADOS WHERE CATEGORIA=’DIRECTIVO’
Queremos saber el número de empleados que tenemos en nuestra empresa suponiendo que el nif es la clave de registro de la tabla empleados. SELECT COUNT(NIF) FROM EMPLEADOS
Ahora queremos saber cuantos de nuestros empleados mayores de 30 están casados. SELECT COUNT(NIF) FROM EMPLEADOS WHERE ESTADO_CIVIL=’CASADO’ AND EDAD>30
Queremos saber la suma de la facturación de una determinada empresa para el año 97. SELECT SUM(TOTAL) FROM FACTURA WHERE CIF_EMPRESA=’A22334455’ AND FECHA BETWEEN ‘1/1/1997’ AND ‘12/31/1997’
Existen otras funciones de cálculo tal vez menos utilizadas por los usuarios, pero muy utilizadas por los informáticos. Ej: MAX, MIN que obtienen el máximo y mínimo valor de un campo respectivamente.
SELECT MAX(PESO) FROM PACIENTES
SELECT MIN(EDAD) FROM EMPLEADOS
PRECAUCIONES USANDO LAS FUNCIONES AVG, SUM Y COUNT.
La precaución principal para no mal interpretar el resultado de estas funciones se refiere a las consultas en las que manejamos varias tablas asociadas o relacionadas entre sí mediante sus claves de registro y claves de referencia.
Veamos como un ejemplo de mala interpretación para la función SUM:
SELECT SUM(E.SALARIO) FROM EMPLEADO E, CONTRATO C WHERE E.NIF=C.NIF_EMPLEADO
Donde Nif es la clave de registro de la tabla empleado y Nif_empleado es la clave de referencia de la tabla de contratos para asociar cada contrato con un empleado, y el salario es un campo de la tabla empleado. En estas circunstancias y suponiendo que un empleado puede tener varios contratos en la base de datos, el resultado de la consulta anterior no sería el esperado. No obtendríamos la suma del sueldo de nuestros empleados. En realidad para cada empleado que tuviese 2 o más contratos su salario se estaría sumando 2 o más veces con lo cual la consulta anterior no tiene sentido.
La consulta correcta para saber la suma total de salarios de nuestros empleados sería:
SELECT SUM(SALARIO) FROM EMPLEADO
Como vemos no necesitamos relacionar los empleados con sus contratos para sumar sus salarios, de hecho si lo hacemos los resultados no serán correctos.
Supongamos ahora que el salario fuese un campo de la tabla de contratos en vez de la de empleados. Si quisiésemos saber la media de salarios que se han pagado el los diez últimos años a empleados con categoría de directivo la siguiente consulta sería correcta:
SELECT AVG(C.SALARIO) FROM EMPLEADO E, CONTRATO C WHERE E.CATEGORIA=’DIRECTIVO’ AND C.FECHA_CONTRATO BETWEEN ‘1/1/1987’ AND ‘12/31/1997’ AND C.NIF_EMPLEADO=E.NIF
La consulta es correcta puesto que aunque un empleado haya tenido un salario distinto por cada contrato a lo largo de su vida en la empresa, y estemos teniendo en cuenta cada uno de estos salarios en el cálculo de la media, es precisamente esto lo que queremos que ocurra. En este caso si es necesario asociar contratos y empleados para seleccionar aquellos contratos pertenecientes a directivos.
CLÁUSULAS PARA ORDENAMIENTO Y AGRUPAMIENTO DE REGISTROS.
Es muy común que le interese ordenar o agrupar los listados obtenidos mediante consultas por uno o más campos. Las cláusulas de ordenamiento y agrupamiento en SQL son respectivamente “ORDER BY” y “GROUP BY” que significan “ordenar por” y “agrupar por”. Veamos un ejemplo sencillo, queremos ordenar el listado de nuestros pacientes solteros por edad y peso.
SELECT * FROM PACIENTES WHERE ESTADO_CIVIL=’SOLTERO’ ORDER BY EDAD, PESO
El listado saliente estaría ordenado por edad y en segundo lugar por el peso de los pacientes. Aunque no en todas las implementaciones del lenguaje SQL es así en general deberán figurar en la lista que viene después de SELECT, todos los campos por los que se esta ordenando.
Ahora veamos un ejemplo de agrupamiento:
SELECT * FROM PACIENTES GROUP BY TALLA, PESO
Obtendría el listado de pacientes agrupados por talla y peso. Aquí siempre debe de figurar, después del SELECT, al menos los campos por los que se agrupa.
Para terminar veamos un ejemplo de consulta, tal vez un poco sofisticada para un curso básico de SQL, pero interesante para observar las amplias capacidades del SQL.
SELECT COUNT(), NOMBRE FROM PACIENTE GROUP BY NOMBRE HAVING COUNT()>1
Estamos empleando la cláusula “HAVING” para indicar una restricción que afecta de modo particular a cada agrupación de registros que el intérprete obtenga. El resultado de esta consulta no es facil de predecir y mucho menos intuitivo, pero bastante útil en algunas ocasiones. Obtendremos una salida parecida a la siguiente:
COUNT NOMBRE 2 Manuel Benítez 5 José Pérez 3 Juan Rodríguez ........................... ...........................
Para cada nombre que se repita más de una vez en la tabla de pacientes presentara el número de veces que se repite y el nombre que se repite. Esto resulta así porque estamos aplicando una función de agregación (COUNT, SUM, AVG...) etc a una consulta donde hemos definido un agrupamiento con GROUP BY, por tanto la función COUNT solo afecta al cada grupo y no a la tabla entera. Otro ejemplo todavía más interesante sería el siguiente:
SELECT AVG(SALARIO),CATEGORIA FROM EMPLEADO GROUP BY CATEGORIA
Obtendríamos cada categoría de empleado y su salario medio.
CONSIDERACIONES CON RESPECTO A LOS VALORES NULOS
Es necesario tener en cuenta que el valor NULL (nulo) al que hicimos referencia en el apartado 3.1, tiene un comportamiento distinto al que intuitivamente cabría esperar, cuando realizamos consultas SQL. Es necesario entender que el valor NULL en un campo de un registro, trata de representar precisamente la ausencia de valor en dicho campo. Si retomamos el ejemplo de los automóviles y sus propietarios, y hacemos la consideración de que un determinado registro de automóvil tiene el valor NULL en su campo Nif_propietario y que un registro de la tabla propietario tiene el valor NULL en su campo Nif. Podríamos pensar que al ejecutar una consulta que asocie propietarios con automóviles, obtendríamos la combinación de estos dos registros en una de las líneas del informe, pero no es así, puesto que esos registros no están asociados, no tienen el mismo valor en los campos citados, sino que carecen de valor en esos campos.
Otro caso en el que es necesario tener precaución con los valores nulos es cuando utilicemos la función COUNT. La consulta SELECT COUNT(NOMBRE) FROM CLIENTES no contara más que aquellos clientes cuyo valor sea distinto de NULL.
RECOMENDACIONES PARA HACER MÁS LEGIBLES SUS CONSULTAS
- Separe las partes SELECT, FROM Y WHERE de su consulta en diferentes líneas identadas con márgenes diferentes. Le será más facil identificar que es lo que obtiene la consulta si la tiene que volver a utilizar en una ocasión posterior.
- Agrupe la lista de campos a recuperar de forma que los campos de cada tabla vayan juntos y sean más fáciles de localizar.
- Agrupe las restricciones que se refieran a los mismos campos o en su caso a las mismas tablas. Si estamos asociando tablas agrupe las condiciones que enlazan una tabla con otra.
- Escriba sus consultas siempre en mayúsculas o en minúsculas. Hay gestores de bases de datos que diferencian los nombres de campo y tabla en mayúsculas o minúsculas (Sybase, Oracle). Si usted cambia de gestor le sera más fácil hacer sus consultas portables al nuevo gestor.
- Escriba las condiciones de más restrictivas a menos restrictivas, dependiendo del gestor utilizado el tiempo de respuesta puede ser inferior.
ESTRUCTURA DE LA BASE DE DATOS
A continuación se presenta la estructura de la base de datos de su aplicación informática, para que usted pueda hacer consultas SQL sobre las tablas descritas. Es necesario hacer una aclaración respecto a la terminología empleada en este manual, que difiere algo de la utilizada para describir la estructura de su base de datos, por la razón de que es más sencilla y legible la descripción con la segunda terminología, siendo mas adecuada la primera para el nivel teórico. En la descripción de la estructura de base de datos, figuran todos los campos bajo el rótulo “CAMPO” y bajo el rótulo “Tipo” el tipo de dato que puede ser: alfanumérico (Letras o números), entero (valores numéricos enteros), real (números reales), boolean o (valor lógico, verdadero ó falso). Después figura el “INDICE” y donde pone “Primario”, los campos que vienen a continuación son la clave de registro de la que hablamos anteriormente. A continuación vienen las tablas relacionadas con la que estamos descr ibiendo, donde pone “maestra” estamos describiendo la relación con una tabla de orden superior, donde pone “detalle” estamos describiendo la relación con una tabla de datos de orden inferior, en el ejemplo de los automóviles y los propietarios, la maestra sería la de los propietarios y la de detalle sería la de los automóviles. En la descripción de las relaciones con tablas maestras, cuando pone “Campos esta tabla” estamos describiendo la clave de referencia y cuando pone “Campos tabla maestra” estamos indi cando la clave de registro de la tabla referenciada. Cuando describimos las relaciones con tablas de detalle, cuando pone “Campos esta tabla” estamos indicando la clave de registro de nuestra tabla, y cuando pone “Campos tabla detalle” estamos indicando las claves de referencia con las que la tabla de detalle referencia a nuestra tabla.
Comentarios
0 comentarios
El artículo está cerrado para comentarios.