UT_4 GBDUT_4 Realización de consultas. En esta unidad aprenderemos a extraer la información de una base de datos estableciendo los requisitos y criterios para seleccionar los datos. Por lo que has estudiado en unidades anteriores, conoces las ventajas que ofrece un SGBD, pero también sabes que si no conocemos la forma de relacionarnos con la base de datos, la información puede estar “disponible” pero no podremos acceder a ella. El SGBD va a ser capaz, a partir de las sentencias, de hacer consultas enlazando las tablas mediante las relaciones definidas en el diseño y en la creación. Por eso es tan importante que todo se haya hecho respetando los criterios establecidos por el modelo, tanto en la fase de diseño lógico como físico. De no hacerlo así nos podríamos encontrar con que, una vez realizado todo el trabajo y después de registrar los datos en las tablas, no tenemos acceso a lo que buscamos, o que la información devuelta por las consultas resulta incoherente. 1.- Herramientas para la realización de consultas. Como sabemos un SGBD integra, además de la base de datos, un conjunto de herramientas que nos facilitan el diseño, la gestión y la administración de la base de datos. En unidades anteriores hemos visto cómo algunas de esas herramientas nos pueden ayudar a establecer tanto el diseño lógico como el diseño físico de la base de datos. En el caso del diseño de consultas también contamos cada vez con un mayor número de utilidades. Podemos hacer una clasificación de estas herramientas en dos tipos: • Herramientas proporcionadas por el SGBD: algunos gestores proporcionan un entorno integrado donde se incluyen asistentes, editores gráficos, etc. En esta categoría nos encontramos con Microsoft Access, OpenOffice Base, Workbench o phpMyAdmin. Las dos últimas se utilizan, exclusivamente, para interactuar con servidores MySQL. • Herramientas externas al gestor: en este caso hablamos de herramientas que añaden funcionalidades y son compatibles con distintas bases de datos. Navicat y HeidiSQL pertenecen a este tipo de herramientas. Durante el presente tema utilizaremos algunas de las herramientas que hemos citado, teniendo en cuenta que se trata solo de algunas de las numerosas herramientas presentes en el mercado, tanto de software libre como propietario. 1.1- Asistentes y herramientas gráficas de diseño de consultas. Tanto incluidos en el propio SGBD, como cuando se trata de aplicaciones externas al propio gestor, existen herramientas gráficas que nos ayudan a realizar consultas a una o más tablas de una base de datos de una forma fácil y sencilla, incluso sin necesidad de conocer el lenguaje SQL. Podemos clasificar esas herramientas en: • Asistentes para consultas. • Herramientas para el diseño consultas. Creación de consultas desde un asistente para consultas: Estos asistentes son aplicaciones que nos permiten seleccionar las tablas, los campos, el orden de las filas, establecer criterios de selección, grupos y cálculos, etc., siguiendo unos pasos muy sencillos. 1 UT_4 GBD Ejemplos de estos asistentes los podemos ver en OpenOffice Base y en Microsoft Access, aunque también incorporan este tipo de asistentes bases de datos como Oracle. Creación de consultas desde la ventana de diseño de consultas: Tanto en los propios SGBD como en aplicaciones que se pueden instalar para aumentar las prestaciones y que son externas al SGBD, podemos encontrar herramientas gráficas para diseñar consultas mediante opciones como: • Representaciones gráficas de tablas y campos. • Opciones con listas desplegables para elegir los tipos de datos, los tipos de índices, etc. • Posibilidad de establecer los criterios de selección, de ordenación, etc, seleccionando opciones o eligiendo operadores, etc. Se trata de herramientas que permiten al usuario elaborar consultas sencillas de forma intuitiva, con el simple manejo de recursos gráficos presentados en una ventana donde se encuentran disponibles todos los elementos que representan las distintas cláusulas que una consulta puede recoger. Aplicaciones como Workbench, phpMyAdmin o Navicat incorporan este tipo de herramientas. Recomendación Accede a la página oficial de Navicat y comprueba qué aplicaciones ofrece para la gestión de servidores de bases de datos. Descarga la aplicación Navicat for MySQL (versión de prueba de 30 días). Instálala en tu ordenador, ejecútala, y recorre las principales opciones. Más adelante usaremos Navicat en algunos ejercicios. También es interesante que te descargues el manual oficial de la aplicación, en formato pdf (está en inglés). 1.2.- Editores de SQL. Aunque hemos citado una serie de herramientas que nos pueden facilitar el diseño de consultas, la herramienta más potente a la hora de establecer criterios para seleccionar la información almacenada en una base de datos, es el lenguaje SQL. Todos los SGBD tienen un editor que, con más o menos elementos de ayuda, nos permite introducir nuestras instrucciones y nos muestra dónde se producen los posibles errores. 2.- El lenguaje de manipulación de datos: LMD. En la unidad anterior clasificamos las sentencias del lenguaje SQL en 3 tipos ¿recuerdas? Lenguaje SQL LDD (Lenguaje de Definición de Datos) LMD (Lenguaje de Manipulación de Datos) LCD (Lenguaje de Control de Datos) Sentencias Incluye sentencias para gestionar las estructuras. Incluye sentencias para gestionar los datos. Incluye sentencias para gestionar la seguridad y los permisos. 2 UT_4 GBD Pues bien, ahora vamos a tratar con el LMD, que es una parte del lenguaje SQL que se encarga de la gestión de los datos almacenados. El LMD tiene instrucciones para ayudarnos a: • Insertar filas (INSERT). • Consultar los datos almacenados (SELECT). • Modificar esos datos (UPDATE). • Borrar filas (DELETE). En esta unidad nos centraremos en la sentencia SELECT, en unidades posteriores se estudiarán el resto de sentencias. Sin ninguna duda, la operación que más veces se realiza sobre una base de datos es la consulta. 3.- Sentencias para crear consultas: SELECT. Como hemos visto, las herramientas gráficas nos ofrecen una gran ayuda a la hora de enviar consultas a nuestra base de datos. Pero sin duda, para tener mayor control sobre cualquier SGBD, y en concreto sobre las consultas a los datos que almacena, Alejandra piensa que lo más seguro es conocer las instrucciones de SQL que integran el LMD. Para realizar consultas se utiliza la sentencia SELECT. Siguiendo el criterio de Alejandra, aprenderemos a utilizar las opciones más importantes de SELECT, desde consultas sencillas sobre una sola tabla, hasta consultas complejas combinando datos de varias tablas, conocidas como consultas multitabla. SELECT es la sentencia que tiene mayores variaciones y opciones sintácticas en todos los SGBD del mercado, y también la más compleja y potente de todas las instrucciones SQL. Utilizaremos esta sentencia para consultar los datos de una base de datos. En la sentencia SELECT el usuario especifica lo que quiere obtener, no cómo, ni dónde. Como hemos dicho presenta muchas opciones. Las más comunes son: SELECT [ALL | DISTINCT | DISTINCTROW ] {Expresión | Columna1, ... | * } FROM TablasReferenciadas [WHERE Condiciones] [GROUP BY {NombreColumna | Expresión | Posición} [ASC | DESC], …] [HAVING Condiciones] [ORDER BY { NombreColumna | Expresión | Posición } [ASC | DESC] , ...] [LIMIT { [desplazamiento,] contador | contador OFFSET desplazamiento} ] Antes de empezar a analizar la función de cada una de las cláusulas de esta sentencia, veremos algunas consideraciones generales: • Para realizar una consulta a una o varias tablas con esta sentencia, es imprescindible utilizar al menos las palabras: o SELECT seguido del nombre de la columna o columnas que se quieran mostrar. o FROM seguido del nombre de la tabla o tablas de las que se obtienen los datos. • El resto de las cláusulas son opcionales, pero en el caso de que se incluyan debe respetarse el orden descrito. • La sentencia SELECT no se limita a nombres de columnas de tablas o a un *, pueden ser otras expresiones, funciones, etc.; incluso aunque no correspondan a ninguna tabla. Un ejemplo se muestra a continuación: SELECT 7*4, SIN(3.1414/2), CURRENT_DATE(); • También es válido, y además necesario cuando se seleccionan varias columnas con el mismo nombre en diferentes tablas, especificar el nombre de la columna separado con un punto del nombre de la tabla. Un ejemplo se muestra a continuación: 3 se puede cambiar usando un alias de columna. como se muestra a continuación: SELECT * FROM TalleresFaber. Es posible asignar un alias a cualquiera de las expresiones de la lista de selección del SELECT. dentro de las cláusulas WHERE. 4 . es conveniente utilizar un alias de columna para evitar que se incluya como cabecera la propia función u operación realizada. la palabra SELECT y la cláusula FROM.CLIENTES. la lista de campos o expresiones que se quieren mostrar en el resultado de la consulta. el formato básico de esta sentencia incluye. Los nombres de las columnas o expresiones que se incluyan en la lista de selección se escriben separados por comas. • Se pueden consultar datos de tablas de una base de datos que no está actualmente en uso. El alias puede usarse dentro de toda la consulta. Para ello.Cláusulas de SELECT I. Una consulta en SQL puede incluir columnas cuyos valores se obtienen haciendo cálculos a partir de los datos almacenados en las columnas de las tablas. como mínimo.Nombre. es el nombre de la columna o campo correspondiente. generalmente más corto. para indicar que se quieren obtener los datos de todos los campos de la tabla o tablas. Cuando queremos mostrar el resultado de la columna calculada dentro de SELECT. 3. Detrás de la palabra SELECT se especificará la lista de selección.UT_4 GBD SELECT CLIENTES.Nombre. es decir.Apellidos FROM CLIENTES. Apellidos. A continuación se asigna un alias al campo CodCliente de una tabla. El encabezado de las columnas que aparece en el resultado de las consultas.Apellidos. Como hemos visto. (FechaSalida – FechaEntrada) AS “Días empleados” FROM REPARACIONES. Se trata de un nombre. La cláusula FROM permite indicar la tabla o tablas que contienen los datos que se quieren consultar. En este caso se conoce como alias de tabla. En el siguiente ejemplo hemos asignado el alias E a la tabla EMPLEADOS. y el alias C a la tabla CLIENTES. CLIENTES C WHERE……… .. Nombre FROM CLIENTES. SELECT CodCliente AS “Código de cliente”. A estas columnas se conocen como columnas calculadas. aunque esta palabra es opcional.Apellidos. separado con un punto del nombre de la tabla. por ejemplo. Un alias se puede utilizar también para asociar un nuevo nombre a una tabla. se escribe tras el nombre de columna la cláusula AS seguida del nuevo nombre que va a aparecer en el encabezado entre comillas. CLIENTES. HAVING o GROUP BY que veremos más adelante. que se utiliza sobre todo cuando consultamos varias tablas y hay nombres de columnas que coinciden. Si éste resulta demasiado largo o es el resultado de un cálculo. SELECT E. Empezaremos por describir su sintaxis y seguiremos con el resto de las cláusulas que más se utilizan. En la lista de selección se puede escribir un *. escribiendo el nombre de la base de datos a la que pertenece. E.Nombre FROM EMPLEADOS E. C. en cualquier referencia a la columna correspondiente. El siguiente ejemplo muestra cómo puede asignarse un alias de columna a una columna calculada: SELECT IdReparación. C.1. por eso los nombres de las columnas van precedidos del alias E ó C seguido de un punto. numemp 5 . que usará alguno de los operadores relacionales y lógicos que veremos en apartados posteriores. Tabla: empleados Clave primaria: numemp Claves foráneas: oficina->referencia a oficinas. Cada campo se definirá del tipo más apropiado para albergar los datos que contendrá. Tras WHERE se escribe una expresión de tipo relacional o de comparación. En el siguiente ejercicio crearemos dicha base de datos. Abajo se describe la estructura y contenido de las tablas que componen dicha base de datos. Ejercicio: Creación de la base de datos bdempleados. Como base de la mayoría de los ejercicios usaremos la base de datos bdempleados. pero solo hay que crear una tabla de empleados. El formato de la condición es: expresión operador expresión Pueden construirse condiciones múltiples con los operadores lógicos AND. del mismo tipo con el que se defina la clave primaria a la que hacen referencia. En una cláusula WHERE se puede usar cualquier función disponible en el SGBD que se esté usando.oficina jefe->referencia a empleados. Obsérvese que se ha duplicado la tabla empleados para poder representar la interrelación reflexiva sobre sí misma. A lo largo de este tema realizaremos numerosos ejercicios para aprender a manejar el lenguaje SQL. e insertaremos algunos datos en sus tablas. así como las relaciones que existen entre las distintas tablas. excluyendo sólo las de resumen. El siguiente ejemplo muestra una consulta que incluye una condición en la cláusula WHERE: SELECT Matricula FROM VEHICULOS WHERE color=”azul” OR marca=”SEAT”. Recuerda que es muy importante definir el tipo de los campos que actúan de clave foránea. Utiliza el cliente gráfico Navicat para crear la base de datos bdempleados en tu servidor MySQL. Estas últimas funciones están diseñadas específicamente para usarse en cláusulas GROUP BY y se verán en otro apartado. OR o NOT. que se creará en un servidor MySQL.UT_4 GBD La cláusula WHERE permite obtener los datos de las filas que cumplen con la condición expresada. numemp Tabla: clientes Clave primaria: numclie Claves foráneas: repclie->referencia a empleados.numemp 6 .UT_4 GBD Tabla: oficinas Clave primaria: oficina Claves foráneas: dir->referencia a empleados. UT_4 GBD Tabla: productos Clave primaria: idproducto Tabla: pedidos Clave primaria: codigo Claves foráneas: clie->referencia a clientes.numclie rep->referencia a empleados.numemp producto->referencia a productos.idproducto 7 . de todas las oficinas cuyo objetivo de venta sea menor de 400000. con encabezado “Ciudad de destino” y la región. Sólo se incluirán en el resultado de la consulta aquellos empleados mayores de 40 años y cuyo contrato fuese formalizado antes de octubre del 88. Es muy importante que se almacenen todas las sentencias que se realicen en los distintos ejercicios. Ejercicio: Alias de columna. Realiza las siguientes consultas en SQL sobre la BD bdempleados: • Seleccionar el nombre de cada empleado y la mitad de su cuota. Realiza las siguientes consultas en SQL sobre la BD bdempleados: • Seleccionar el nombre de todos los empleados. con encabezado “Número de oficina”. encabezando estos valores con el título “Años restantes de trabajo”. • Seleccionar el nombre de cada empleado y el número de años que le restan para jubilarse. Puedes escribir las consultas en la línea de comandos o en cualquier cliente gráfico de MySQL. Sólo aparecerán los datos de los empleados para los cuales el doble de sus ventas sea mayor que 650000 y menor que 800000. El formato de la salida será: Ciudad oficina: ciudad – Código director: dir – Mitad diferencia: resultado Nota: Condiciones para fechas -> WHERE MONTH(fecha)=12 AND YEAR(fecha)<2014 8 fecha < "12/3/2014" ---- WHERE . haciendo que aparezca como título de la columna “Nombre de empleado”. la ciudad. Para ello puedes utilizar cualquier editor de texto plano.UT_4 GBD Recomendación Todas las consultas que se piden en los ejercicios deben probarse sobre el servidor MySQL. El encabezado de la mitad de su cuota será “Mitad de la cuota”. • Seleccionar el nombre de la ciudad. el código del director de la oficina y la mitad de la diferencia entre ventas y objetivo. de todas las oficinas para las que el 30% de las ventas sea mayor que el 15% del objetivo. • Seleccionar el número de oficina. Ejercicio: Columnas calculadas. En este caso. MAX(). SUM(). Se puede elegir el orden ascendente o descendente añadiendo a continuación ASC o DESC. ordenado ascendentemente por modelo: SELECT Marca. Tanto la cláusula GROUP BY como HAVING se tratarán más adelante en el apartado de consultas agrupadas. El siguiente ejemplo muestra un listado de las matrículas de los vehículos que han sufrido reparaciones. permite hacer selecciones en situaciones en las que no es posible usar WHERE. Modelo ASC. Estas funciones también se pueden usar sin la cláusula GROUP BY siempre que en la consulta no se seleccionen otras columnas. En las consultas de agrupadas se suelen usar funciones de resumen o reunión. La cláusula ALL permite que se puedan presentar todas las filas afectadas por el resto de condiciones de la consulta aunque algunas estén repetidas. etc. Por ejemplo: COUNT().10. entonces se devolverán todas las filas hasta la última. evitaremos que su matrícula aparezca repetida. el primero indica el número de la primera fila y el segundo el número de filas a recuperar. Es la opción por defecto. SELECT DISTINCT Matricula FROM REPARACIONES. AVG(). Modelo FROM VEHICULOS ORDER BY Marca ASC. La cláusula LIMIT permite limitar el número de filas devueltas por una consulta. La cláusula WHERE no se puede aplicar a columnas calculadas mediante las funciones de reunión que hemos mencionado en el apartado anterior. A continuación pueden verse varios ejemplos del uso de LIMIT: mysql> SELECT * FROM table LIMIT 5. la cláusula DISTINCT se usan cuando no queremos que se presenten en el resultado filas repetidas.Cláusulas de SELECT II. SELECT ALL Matricula FROM REPARACIONES. su matrícula aparecerá repetida. # Devuelve las filas 6-15 9 . Si el segundo argumento es -1. también conocidas como funciones de columna. Es posible agrupar las filas que devuelve una consulta según los valores de una columna usando la cláusula GROUP BY. En concreto. ordenado alfabéticamente por marca y. y es parecida a la cláusula WHERE. • Cuando se usan dos valores. Si el vehículo se ha reparado más de una vez. A continuación se obtiene un listado con la marca y el modelo de los vehículos que se reparan en nuestro taller. La cláusula HAVING suele utilizarse en combinación con la cláusula GROUP BY. LIMIT puede admitir uno o dos parámetros: • Cuando se usa un solo valor indica el número de filas devueltas. En este caso se denominan consultas de resumen. Estas consultas se denominan consultas agrupadas y las veremos en esta unidad. Por el contrario. MIN().UT_4 GBD 3. VARIANCE(). La cláusula ORDER BY permite obtener los datos ordenados ascendente o descendentemente con relación a una o varias columnas.2. Se suele utilizar para no sobrecargar demasiado al servidor o a la aplicación que va a recibir los resultados de la consulta. A continuación se muestra un listado de las matrículas de los vehículos que han sufrido reparaciones. Por defecto se usa el orden ASC. si el vehículo se ha reparado más de una vez. STD().. en caso de coincidencia. El resultado aparecerá ordenado por beneficios. # Devuelve las 5 primeras filas. mysql> SELECT * FROM table LIMIT 95. en este caso MySQL. Descripcion.<br /> Ejercicio resuelto Queremos consultar la referencia. y que le ayudarán. No se incluirán en el resultado de la consulta aquellos empleados cuyo beneficio no sea superior a 80000.. El resultado aparecerá ordenado ascendentemente por región. entre otras cosas. la fila 5 es la sexta.UT_4 GBD Nota: empieza a contar desde cero. Aunque ya hemos usado algunos operadores que pueden intervenir en una sentencia SQL. • Seleccionar el nombre y la edad de todos los empleados cuya edad esté comprendida estrictamente entre 45 y 65. Los nombres aparecerán ordenados por la edad.-1. Veremos los operadores de que dispone MySQL. ORDER BY y HAVING y además se pueden emplear directamente en las sentencias. es decir. mysql> SELECT * FROM table LIMIT 5. El encabezado de la primera columna será “Empleados mayores”. dado que en la mayor parte de los casos se incluyen en sentencias de tipo SELECT. descripción e importe de las 10 actuaciones más baratas que se pueden llevar a cabo en nuestro taller. • Selecciona los tres primeros registros de la tabla pedidos. tercera y última columna de la tabla empleados.Operadores. DISTINCT. SELECT Referencia. Aparecerán todos los registros ordenados descendentemente por la tercera columna. • Selecciona los registros del 2º al 5º de la tabla pedidos. Importe FROM ACTUACIONES ORDER BY Importe LIMIT 10. Descripcion. 4. Los operadores se utilizan para construir expresiones que se usan en cláusulas WHERE. Ejercicio: ALL. a establecer condiciones de búsqueda básicas. Ejercicio: ORDER BY. • Selecciona el tercer registro de la tabla pedidos. # Devuelve las filas 96-última. Este último dato aparecerá con el encabezado “Beneficios de empleado”. ascendentemente. Solution: SELECT Referencia. • Seleccionar el nombre de empleado y el 25% de sus ventas. Una vez vistas las cláusulas que pueden intervenir en una consulta. y descendentemente por ciudad. pero la mayoría de ellos son compatibles con otros SGBD. de mayor a menor. Alejandra considera importante conocer también los operadores que se pueden usar dentro de las expresiones en el SGBD que está utilizando. Importe FROM ACTUACIONES ORDER BY Importe LIMIT 10. • Seleccionar la región y la ciudad de todas las oficinas que no estén en el norte ni tengan menos de 300000 euros de objetivo de ventas. Realiza las siguientes consultas en SQL sobre la BD bdempleados: • Seleccionar la primera. Los años aparecerán ordenados cronológicamente. LIMIT Realiza las siguientes consultas en SQL sobre la tabla pedidos de la BD bdempleados: • Seleccionar los años en que se realizaron algún pedido (sin repeticiones). vamos a ampliar en este apartado los tipos de operadores. 10 . Con el lenguaje SQL podemos utilizar muchos operadores diferentes para cada tipo de columna. (Veremos el valor almacenado 10) Una variable sin asignar será de tipo cadena y su valor será NULL. fechas.Operador de asignación y Operadores aritméticos. constantes. Reflexiona En caso de que tengas que combinar varios operadores en una misma expresión. etc. campos booleanos. Si en una expresión aparecen varios operadores. Operador de asignación: En MySQL podemos crear variables y usarlas posteriormente en expresiones. se verá en otro apartado más adelante) SELECT Apellidos. Los operadores de mayor prevalencia se evalúan primero y así hasta los de menor prevalencia. Por ejemplo: SET @hoy= CURRENT_DATE(). Los paréntesis tienen mayor prevalencia que cualquier operador. nombre y dirección de los empleados de Talleres Faber que viven en Cantabria. SELECT @X. Dirección FROM EMPLEADOS WHERE CP LIKE ‘39%’.. SELECT @hoy. binarios. Nombre. (Veremos la fecha actual) • Utilizando el operador de asignación :=. se evalúan en un orden determinado. es aconsejable que utilices tantos paréntesis como consideres necesario para que éstos se evalúen en el orden que te interese. Se establece como condición que los dos primeros caracteres del código postal sean 39. cadenas de caracteres. De este modo evitarás sorpresas desagradables. Cuando dos o más operadores tienen igual prevalencia.mysql.com/doc/refman/5. funciones y otras expresiones) que se combinan unos con otros. Se pueden utilizar con números.UT_4 GBD Los operadores sirven para construir expresiones. Podemos crear variables de dos formas: • Con SET. En el siguiente ejemplo hemos consultado los datos apellidos. En una expresión en la que se utilicen paréntesis para agrupar parte de los elementos de la expresión.6/en/operatorprecedence.html. 11 . Debes conocer Para consultar el orden de prioridad de los operadores disponibles en MySQL pincha en el siguiente enlace: Orden de prioridad de los operadores: http://dev. 4. Una expresión es una combinación de operadores y operandos (como campos. se evalúan primero los paréntesis más internos y con lo que se obtiene se van evaluando los paréntesis siguientes hasta los más externos. Por ejemplo: SELECT @X:=10. (No te preocupes por el operador LIKE. se evalúan de izquierda a derecha. variables.1. Multiplicación y división. fechas. Estos operadores son habituales en cualquier lenguaje de programación. Exponenciación. el orden de prevalencia es: 1. % o mod Dividen dos números y devuelven el resto entero de la división. Estos operadores devuelven los valores lógicos de verdadero o falso. sin son iguales y 0. MySQL dispone de los operadores aritméticos habituales: suma. 2. < Menor. - Se utiliza para hallar la diferencia entre dos números y. pero algunos lenguajes como MySQL añade algunos muy útiles que se usan frecuentemente.. resta. Los operadores de mayor prevalencia son los aritméticos. multiplicación. división. si son diferentes. etc. 4. / Se utiliza para dividir dos números. El resultado siempre es un valor numérico. Para crear expresiones lógicas disponemos de los operadores de comparación que se aplican a cualquier tipo de columna: cadenas. 3. \ Se utiliza para dividir dos números y el resultado cociente en forma de entero (división entera) entero. Suma y resta. * Se utiliza para multiplicar dos números. Operador Significado <= Menor o igual. para simbolizar signo negativo de un número.UT_4 GBD Operadores aritméticos: Los operadores aritméticos se aplican a valores numéricos. para simbolizar signo positivo de un número. potencia. y entre ellos. >= Mayor o igual = Compara dos expresiones y devuelve 1. como operador unario. entero o en coma flotante. Operadores de signo.Operadores de comparación. 4. (1 ó 0). 12 . etc. números. ^ Se utiliza para elevar un número a la potencia del exponente (número ^ exponente).2. Operador Significado + Se utiliza para sumar dos números y. como operador unario. ya sean enteros o en coma flotante. > Mayor. - Se obtiene un valor de signo contrario. el resultado es verdadero (1). • Las cadenas constantes se han de expresar encerradas entre comillas dobles o simples. 2. Comparación de cadenas de caracteres y de fechas: Los operadores relacionales pueden usarse para comparar cadenas. se considera menor cuánto más antigua sea. es decir. el resultado no es NULL. < > ó != Si las expresiones comparadas son diferentes. Si solo una de las dos expresiones es nula. el resultado es verdadero. Estos operadores tienen todos ellos la misma prioridad. • Cuando se comparan cadenas. pero MySQL añade un tercer valor: desconocido para poder trabajar con valores NULL.Operadores lógicos. los operadores AND y OR se pueden asociar. Solo existen dos valores posibles para los resultados: verdadero y falso.UT_4 GBD <=> Funciona como =. el orden de prevalencia es el siguiente: 1.. 4. 3. Los operadores lógicos se usan para crear expresiones lógicas complejas. devuelve TRUE y si ambos son verdaderos o falsos devuelve FALSE. 4. Si el operador es NULL devuelve NULL. entonces el resultado es falso (0). Todos estos operadores tienen menor prevalencia en las expresiones que los operadores aritméticos. a no ser que se realicen sobre campos definidos con el atributo BINARY. Entre ellos. y si son iguales. Si se comparan dos expresiones nulas. • Si son fechas. OR ó || Devuelve el valor TRUE si cualquiera de las dos condiciones es verdadera y FALSE cuando las dos condiciones son falsas NOT ó ! Devuelve lo opuesto a la condición que sigue a NOT. Operadores de comparación Operador NOT Operador AND Operador OR Al igual que todos los operadores binarios que veremos. XOR Devuelve NULL si cualquiera de los operadores es NULL.3. se pueden crear expresiones como 13 . Cuando uno de los operadores es verdadero. salvo que si una de las dos expresiones o las dos es nula. se considera menor la cadena que aparezca antes por orden alfabético no distinguiendo entre mayúsculas y minúsculas. 1 TRUE 0 FALSE desconocido NULL Operador Función AND ó && Devuelve el valor TRUE cuando las dos condiciones son verdaderas y FALSE si alguna de ellas es falsa. el resultado es falso. Apellidos FROM CLIENTES WHERE Apellidos NOT LIKE “%Sánchez%”. y el resultado. 4. Apellidos FROM CLIENTES WHERE Apellidos LIKE “M%”. Matricula FROM REPARACIONES WHERE (FechaEntrada>=’2014-01-01’ AND km<100000) AND Reparado=False.UT_4 GBD A AND B AND C. Por ejemplo. a no ser que en la comparación se vea involucrado un campo definido como BINARY. Su sintaxis es: Expresión [NOT] BETWEEN ValorInicial AND ValorFinal 14 . el resultado es NULL.. que sirven para comprobar si una expresión está comprendida en un determinado rango de valores. R. Y para obtener los nombres y apellidos de los clientes cuyo apellido no sea Sánchez escribiríamos: SELECT Nombre. Matricula FROM REPARACIONES WHERE (FechaEntrada>=’2014-01-01’ AND km<100000) AND Reparado=False. y estas expresiones se evalúan de izquierda a derecha.Operadores especiales. La sintaxis de LIKE es: Expresión [NOT] LIKE patrón En SQL de MySQL tenemos dos caracteres especiales que pueden aparecer en cualquier posición del patrón: Comodín Significado % Representa a cualquier cadena de 0 o más caracteres. y que hayan salido del taller sin reparar: SELECT IdReparacion. se usa como primer operando de la siguiente operación R AND C. Tanto si la cadena como el patrón son NULL. El hecho de que se requieran dos operandos significa que las operaciones se realizan tomando los operandos dos a dos. para obtener los nombres y apellidos de los clientes cuyo primer apellido comience por la letra M haríamos lo siguiente: SELECT Nombre. Otros operadores especiales son BETWEEN y NOT BETWEEN.4. LIKE no distingue entre mayúsculas y minúsculas. En MySQL disponemos de los operadores LIKE y NOT LIKE para comparación de cadenas. y que se utilizan para construir las condiciones de WHERE y HAVING. Primero se evalúa A AND B. _ Representa a un carácter cualquiera. Solution: SELECT IdReparacion. Ejercicio resuelto Consultar las matrículas de los vehículos que hayan entrado a reparar en 2014 con menos de 100000 Km. IN. El operador IN devuelve 1 (verdadero) si el valor de una expresión es igual a alguno de los valores de una lista. Descripcion FROM ACTUACIONES WHERE TiempoEstimado BETWEEN 0.60. que es la barra invertida o contrabarra. Su sintaxis se indica a continuación: Expresión IN [NOT IN] (Valor1. Ejercicio: BETWEEN. Descripcion FROM ACTUACIONES WHERE TiempoEstimado >=0. Del carácter de escape se habló en el recurso: Reglas para escribir sentencias SQL de la unidad anterior. Los últimos operadores especiales que comentaremos en este apartado son IN y NOT IN. Reflexiona Observa la diferencia entre las dos soluciones del ejemplo anterior: • Con BETWEEN la expresión que se evalúa se escribe una sola vez. ……. Ejemplo: Queremos ver el Nombre de una serie de artículos que en la columna IVA contienen el símbolo % al final. para obtener un listado con los números de referencia y la descripción de las actuaciones cuyo tiempo estimado de realización esté entre 30 y 60 minutos. • En el segundo ejemplo las expresiones a ambos lados de AND deben escribirse completas. Valor2. éste deberá ir precedido de un carácter de escape. mediante la siguiente consulta: SELECT Matricula FROM VEHICULOS WHERE Marca IN (‘Seat’. Del carácter de escape se habló en el recurso: Reglas para escribir sentencias SQL de la unidad anterior. ‘Peugeot’). y cuyas ventas no estén comprendidas entre 50000 y 250000 ni entre 300000 y 500000 (usa BETWEEN siempre que sea posible). que es la barra invertida o contrabarra.30 AND 0. LIKE Realiza las siguientes consultas en SQL sobre la tabla empleados de la base de datos bdempleados: • Seleccionar los nombres de los empleados cuya cuota de venta esté comprendida entre 250000 y 300000. éste deberá ir precedido de un carácter de escape. Ford o Peugeot. ‘Ford’.UT_4 GBD Por ejemplo. Retroalimentación: Para poder buscar un carácter % ó _ como carácter dentro de una cadena. podríamos escribir cualquiera de las dos siguientes consultas: SELECT Referencia. y falso en caso contrario. SELECT Nombre FROM ARTICULOS WHERE IVA LIKE ‘%\%’.30 AND TiempoEstimado <= 0. Ejemplo: Queremos ver el Nombre de una serie de artículos que en la columna IVA contienen el símbolo % al final. SELECT Nombre FROM ARTICULOS WHERE IVA LIKE ‘%\%’. Reflexiona ¿Cómo buscaríamos en una cadena el carácter % ó el _? Para poder buscar un carácter % ó _ como carácter dentro de una cadena. ) Podríamos obtener un listado de matrículas de los vehículos que hemos registrado de las marcas: Seat. El operador NOT IN devuelve 1 (verdadero) si el valor de la expresión no está en la lista. SELECT Referencia.60. 15 . En el resultado no aparecerán los empleados cuyo jefe sea el de código 108 (usa BETWEEN e IN). para comprobar si en una columna hay algún valor. para los que no se ha definido una fecha de salida. • Seleccionar el código y el nombre de la provincia de todas las oficinas que no tengan ni objetivo de ventas ni ventas. FechaEntrada FROM REPARACIONES WHERE FechaSalida IS NULL. los datos pertenecen a diferentes tipos: cadenas de caracteres. 16 . • Seleccionar el nombre de los empleados cuyo título no sea director de nada. Un dato es una unidad de información con sentido que se almacena en un campo. que el valor de ese dato es desconocido.. Un valor nulo es un valor que no es asignable a ningún tipo de datos y que significa que no se ha definido ningún valor inicial para ese dato. o bien que el objetivo de ventas o las ventas sean 0. SELECT Matrícula. es decir. o su superávit mayor de 100000. no se cargó en su momento ningún valor.UT_4 GBD • Seleccionar el nombre y las fechas de los contratos de los empleados cuyos contratos se formalizasen entre 1989 y 2000. fechas.Tratamiento de valores nulos. • Seleccionar el nombre y la edad de los empleados cuyo primer apellido no comience ni por G ni por V (supón que todos los nombres propios son simples). etc. Se dice que el contenido de una columna para un registro determinado es NULL si está completamente vacía. o bien su oficina sea la 21. Para comprobar si en una columna hay un valor nulo se utiliza la expresión: NombreColumna IS NULL Por el contrario. por tanto el campo tiene un contenido: el cero o el espacio en blanco. Un cero o un espacio en blanco es un valor que se ha asignado a un campo. Debes conocer Los operadores aritméticos devuelven un valor nulo cuando alguno de sus operandos es nulo. o números. es decir. 5. Ejercicio: IS [NOT] NULL Realiza las siguientes consultas sobre la base de datos bdempleados: • Seleccionar los nombres de los empleados que no tengan jefe o no pertenezcan a ninguna oficina. se emplea la expresión: NombreColumna IS NOT NULL La siguiente consulta muestra la matrícula y la fecha de entrada de los vehículos que están actualmente en nuestro taller de reparaciones. la 13 o la 22. Dependiendo del contenido de la información almacenada. Sólo se visualizarán los nombres de empleados que no tengan asignada cuota de venta. Se utilizan en cláusulas SELECT. números y caracteres especiales. obtener la fecha y hora actuales.9) | +--------------+ | 2 | +--------------+ De forma general. Funciones de cadena de caracteres: • Estas funciones trabajan con datos de tipo carácter.00 sec) +--------------+ | mod(29. mysql> SELECT MOD(29. podemos clasificar las funciones en las siguientes categorías: Funciones aritméticas: • Estas funciones trabajan con datos de tipo numérico. • Mediante estas funciones podremos calcular el número de caracteres de una cadena. Las funciones pueden: • Modificar la información original de la tabla. • Se deben encerrar entre comillas simples. el formato de almacenamiento de las fechas es AAAA-MM-DD y de las horas HH:MM:SS. • Los literales numéricos no se encierran entre comillas. etc. Esta función requiere dos argumentos que. Las funciones se usan dentro de expresiones y actúan sobre los valores de las columnas de las tablas. con variables o con constantes. etc. Funciones de manejo de fechas y horas: • En MySQL existen numerosas funciones para trabajar con las fechas y las horas. son dos valores constantes. • Por defecto. en este caso. el punto decimal.Funciones.UT_4 GBD 6. añadir o eliminar caracteres a la izquierda o a la derecha. En MySQL es importante que entre el nombre de la función y el paréntesis no exista ningún espacio en blanco. WHERE. pero existen muchas funciones que nos permiten descomponer la fecha y la hora. • Los datos de tipo numérico incluyen los dígitos del 0 al 9. • Indicar alguna información sobre el elemento al que se aplica. Funciones de comparación: 17 .. Una función está caracterizada por un nombre y cero o más argumentos encerrados entre paréntesis. convertir una cadena a mayúsculas o a minúsculas. que devuelve el resto de la división entera de dos valores. ORDER BY.9). y el signo menos. En el siguiente ejemplo se muestra la ejecución de la función MOD de MySQL. 1 rows in set (0. • Este tipo de datos incluyen cualquier carácter alfanumérico: letras. etc. • Selecciona todos los registros que contengan una t en el primer campo. y otro la letra t. respectivamente. Realiza las operaciones de abajo. Ejercicio: Funciones numéricas. • Selecciona todos los registros que no contengan una T en el segundo campo. Puedes recurrir al manual de MySQL para buscar información sobre las funciones necesarias para realizar el ejercicio. Al menos uno de los datos del primer campo contendrá la letra T. respectivamente. Crea una nueva base de datos llamada bdfunciones. • Selecciona todos los registros de la tabla ordenados por el código ASCII del segundo carácter del segundo campo. • Utiliza Workbench para añadir cuatro registros a la tabla creada. no el nombre del mes. • Añade a la base de datos creada una nueva tabla.: http://dev. Utiliza una función para hacer referencia al valor de esta constante. entero normal. Ejercicio: Funciones de manejo de cadenas.mysql. tres dígitos decimales a cada valor de los dos últimos campos. VARCHAR(20) y entero. • Desde Navicat. pero cambiando cada carácter por el siguiente en la tabla de códigos ASCII (ej: ‘ABCD’ se cambiaría a ‘BCDE’). Debes conocer En el siguiente documento te presentamos un resumen de las funciones de cada tipo que se utilizan con más frecuencia en MyQL y algunos ejemplos de aplicación: Resumen de las funciones más frecuentes en MySQL. • Selecciona el código ASCII de la última letra del primer campo de todos los registros. llamada funcionescadena. inserta 5 registros en la tabla creada. En algunas herramientas gráficas se encuentran accesibles todas las funciones disponibles agrupadas por categorías. Recuerda que puedes buscar en el manual de MySQL las funciones predefinidas apropiadas para realizar las consultas. • Añade a la base de datos bdfunciones una nueva tabla llamada usofuncionesnumericas. Para consultar la documentación relativa a las funciones del manual de MySQL en español pincha en el siguiente enlace: Funciones internas para MySQL. al menos. con 3 campos de tipos VARCHAR(100) BINARY. • Selecciona la concatenación de las 3 últimas letras del primer campo seguidas de la cadena ‘YYY’ y seguidas de las dos primeras letras del segundo campo. El primer campo será la clave principal. A continuación.(Anexo del tema) Para saber más Como hemos dicho. realiza las operaciones de abajo.html de la fecha.UT_4 GBD Se trata de funciones que comparan los valores de cada una de las columnas en el interior de una fila para obtener: el menor o el mayor valor de ellos. Los datos insertados en los campos de tipo VARCHAR serán frases compuestas por varias palabras. Ejecuta las sentencias en el cliente de línea de comandos o en cualquier cliente gráfico de MySQL. Esta nueva tabla estará compuesta por cuatro campos de tipo entero pequeño. • Selecciona el resultado de multiplicar el primer y el segundo campo de la tabla por el valor de la constante Π (PI).com/doc/refman/5. siendo el primero la clave principal. Añade. • Selecciona la secuencia de caracteres correspondiente a los cuatro primeros caracteres de la cadena contenida en el primer campo.6/en/functions. 18 . • Visualiza el contenido completo de la tabla. real simple y real doble. • Selecciona todos los registros que contengan una T en el primer campo. existen muchas funciones que pueden aplicarse a las columnas de una tabla. así como comprobar si el valor de una columna es nulo. si no se especifica. Debe observarse que si no se especifica la cláusula WHERE. En las consultas realizadas hasta ahora sólo hemos utilizado una tabla que se indicaba a la derecha de la cláusula FROM. el resultado será el producto cartesiano.UT_4 GBD • Visualiza la raíz cuadrada de todos los valores contenidos en el cuarto campo. El producto cartesiano no suele ser un resultado relevante. • Utiliza Workbench para añadir a la tabla tres registros. • Selecciona los nombres del día y del mes de las fechas contenidas en el tercer campo. Algunas fechas estarán dentro de los últimos 30 días. Cuando utilizamos varias tablas tenemos que tener en cuenta: • Se pueden unir tantas tablas como deseemos. date. siendo el primero la clave principal. Hasta ahora nos hemos dejado guiar por Alejandra para aprender a realizar consultas sencillas que manejaban una sola tabla. • Si hay columnas que tienen el mismo nombre en distintas tablas de la cláusula FROM.CodCliente = VEHICULOS. datetime y time.Consultas multitabla.CodCliente. En el siguiente ejemplo se obtiene un listado con los nombres y apellidos de los clientes y las matrículas de los coches que nos han traído a reparar al talle. Ejercicio: Funciones de manejo de fechas y horas. dividida por 4. SELECT Nombre. • Selecciona todos los registros que tengan un valor de segundo impar en el tercer o en el cuarto campo. se deben especificar escribiendo el nombre de la tabla antes del nombre de la columna: NombreTabla. 19 . pero es conveniente. Matricula FROM CLIENTES. • Selecciona el valor del primer campo de la tabla para todos aquellos registros que tengan en el tercer campo una fecha que esté dentro de los últimos 30 días. de todos los registros que contengan en el segundo campo una fecha que pertenezca a la primera mitad de cualquier año o al mes de septiembre. • En la cláusula WHERE es necesario especificar el criterio que se sigue para combinar las tablas ya que.NombreColumna • Si el nombre de una columna no coincide en dos tablas no es necesaria la notación anterior. • En la cláusula SELECT se pueden citar columnas de todas las tablas. Realiza las siguientes operaciones: • Añade a la base de datos bdfunciones una nueva tabla llamada usofuncionesfechahora. pero hay veces que una consulta necesita columnas de varias tablas. VEHICULOS WHERE CLIENTES. Está claro que en el diseño de Talleres Faber intervienen múltiples tablas y que en el trabajo diario con la base de datos estas consultas van a ser frecuentes.. se obtiene el producto cartesiano de las tablas CLIENTES y VEHICULOS. que combina todas las filas de una tabla con cada una de las filas de la otra. • Visualiza el resultado de redondear con 2 decimales los valores de los dos últimos campos. Apellidos. 7. Esta nueva tabla estará compuesta por cuatro campos de tipo entero pequeño autonumérico. • Visualiza el resultado obtenido al elevar el valor el contenido del tercer campo al valor contenido en el segundo campo. Ha llegado el momento de realizar consultas más complejas para obtener datos de varias tablas. Tendremos que seguir los pasos de Alejandra para aprender a combinar las tablas y hacer consultas que muestren los resultados buscados. su fecha de contrato y la oficina en la que trabaja. incluyendo la ciudad de la oficina así como sus ventas. En este ejemplo se efectúa el producto cartesiano de la tabla de empleados con ella misma. junto con las horas trabajadas en cada intervención.UT_4 GBD Para consultar los datos personales de los empleados cuya categoría sea "oficial". Estas funciones se muestran en la siguiente tabla: FUNCIONES DE COLUMNA COUNT(Expresión o Columna) Descripción Cuenta el número de valores no nulos de la columna que aparece como argumento. oficina y título de la tabla empleados. Observa la forma de nombrar los campos en la tabla resultado. su nombre. Apellidos. Intervienen WHERE EMPLEADOS. tal y como hemos explicado. En muy pocos casos nos interesa mezclar filas de una tabla con filas de otra. empleados AS emp Reflexiona Cuando realizamos consultas a varias tablas y no especificamos las columnas por las que se relacionan. el producto cartesiano de estas tablas. sin ningún criterio para establecer esa combinación. Ejemplo: si combinamos en una consulta CLIENTES con VEHICULOS sin hacer coincidir el CodCliente en ambas tablas. Este resultado casi siempre será un error. para cada trabajador menor de 45 años. obtendremos un listado que mezcla cada cliente con todos los vehículos de la tabla. • Los campos nombre. • Todos los campos y registros de las tablas empleados y oficinas. 8. sobre la base de datos bdempleados. • Obtén una relación que contenga.CodEmpleado AND Categoria LIKE “Oficial%”. SQL proporciona un conjunto de funciones que nos permiten resumir datos de la base de datos. Horas FROM EMPLEADOS. • En este apartado efectuaremos el producto cartesiano de la tabla productos consigo misma. Las funciones de grupos de valores ignoran los valores nulos a la hora de realizar los cálculos. Podemos utilizar la cláusula DISTINCT para contar el número de 20 .. y los campos oficina. Desde un punto de vista lógico esta consulta no tendría ningún sentido. su título. el resultado de la consulta es el producto cartesiano. Es decir. Debe observarse que en este caso resulta obligatorio el uso de un alias de tabla. Ejercicio: Consultas multitabla y producto cartesiano. Como hemos mencionado anteriormente. las siguientes consultas: • Obtener todos los campos de todos los registros de las tablas productos y pedidos. como si fuese un total final. No se incluirán en el resultado tuplas cuyo campo título sea “representante”. No se incluirán en el resultado tuplas en las que ambos identificadores de fabricante sean idénticos. pero sólo el identificador de fabricante y la descripción del producto de la segunda. Realiza.CodEmpleado = Intervienen. Estas funciones actúan sobre un grupo de filas para obtener un único valor. edad. ciudad y region de la tabla oficinas. Obtendremos todas las posibles combinaciones de empleados con empleados. ejecutaríamos la siguiente consulta: SELECT DNI. Nombre. Se incluirán todos los campos de la primera relación.Consultas de resumen. SELECT * FROM empleados. MIN(Expresión o Columna) Obtiene el valor mínimo del argumento indicado. una sola fila. Reflexiona Analiza las siguientes consultas: SELECT COUNT(DISTINCT Marca) “MARCAS” FROM VEHICULOS. 3. A continuación se obtiene el número total de horas trabajadas por los empleados: SELECT SUM(Horas) FROM Intervienen. una sola fila. Si la marca aparece repetida se cuenta una sola vez. Eliminaría las filas duplicadas que devuelva la consulta. Eliminaría las filas duplicadas que devuelva la consulta. SELECT DISTINCT COUNT(Marca) “MARCAS” FROM VEHICULOS. El argumento de estas funciones suele ser un nombre de columna. En la segunda consulta la cláusula DISTINCT se aplica después de contar. Ejercicio resuelto Realiza las siguientes consultas a las tablas de TalleresFaber: • Precio medio de los recambios. SELECT count(DISTINCT Matricula) AS “Número de vehículos” FROM REPARACIONES WHERE FechaEntrada BETWEEN “2011-01-01” AND “2011-01-31”. ¿De qué forma interviene la cláusula DISTINCT en ambas? En la primera consulta contamos en la tabla VEHICULOS cuantas marcas distintas aparecen. por tanto no es posible que haya duplicados. • Número de vehículos que nos visitaron en Enero. En la segunda consulta la cláusula DISTINCT se aplica después de contar.UT_4 GBD valores diferentes que aparecen en la columna. SELECT Max(HorasEmpleadas) AS “Horas empleadas” FROM REPARACIONES. Solución: 21 . por tanto no es posible que haya duplicados. 2. Si la marca aparece repetida se cuenta una sola vez. MAX(Expresión o Columna) Obtiene el valor máximo del argumento indicado. • Tiempo máximo que dura una reparación. AVG(Expresión o Columna) Obtiene la media aritmética del argumento indicado. Si escribimos * cuenta las filas que tengan valor no nulo. 1. SUM(Expresión o Columna) Calcula la suma de los valores numéricos indicados en el argumento. En este caso no tiene sentido porque la consulta devuelve un único valor. Retroalimentación: En la primera consulta contamos en la tabla VEHICULOS cuantas marcas distintas aparecen. No considera los valores nulos. En este caso no tiene sentido porque la consulta devuelve un único valor. SELECT Avg(PrecioReferencia) AS “Precio medio recambios”FROM RECAMBIOS. En el apartado anterior hemos usado funciones de columna para calcular totales. SELECT Max(HorasEmpleadas) AS “Horas empleadas” FROM REPARACIONES. • Queremos visualizar el número de tuplas obtenido al realizar el producto cartesiano de la tabla pedidos y la tabla clientes. Las consultas agrupadas nos permitirán realizar cálculos de grupo sobre filas que tienen un valor coincidente en una o varias columnas. Este resultado aparecerá con el título “Desviación media”. • Visualizar la fecha del último pedido que se hizo de un producto fabricado por aci. usando las funciones de columna: • Se pretende calcular la media de las edades de los empleados mayores de 50 años.Consultas agrupadas. No se considerarán los empleados que tengan un nulo en su campo cuota o en su campo ventas. Alejandra piensa que podrá encontrar soluciones a cuestiones que hasta ahora no podía resolver y que pueden ser útiles. SELECT Avg(PrecioReferencia) AS “Precio medio recambios”FROM RECAMBIOS. Cuando hemos recorrido con Alejandra las cláusulas de la sentencia SELECT. El título de este resultado será “Cuenta cartesiano”. • Visualizar la mayor edad de entre los empleados contratados antes de 1988. Ejercicio: Consultas de resumen y funciones de columna. • Queremos visualizar el número de valores no nulos contenidos en la columna oficinas. ¿cuántos coches de cada marca han visitado nuestro taller? Hasta ahora lo que podíamos hacer era mostrar las filas de la tabla automóviles.UT_4 GBD 1. por ejemplo. Por ejemplo. Combinando estas cláusulas con las funciones de columna del apartado anterior. • Se pretende calcular la media de las diferencias de las ventas de cada empleado menos las ventas de la oficina que tiene asignada.. 2. de la siguiente forma: 22 . hemos visto que podíamos utilizar GROUP BY para agrupar filas y HAVING para establecer condiciones en las filas agrupadas. Ejecuta sentencias para llevar a cabo las siguientes consultas sobre la base de datos bdempleados.objetivo de la relación que se obtiene al realizar el producto cartesiano de la tabla empleados y la tabla oficinas. obteniendo un único dato resumen. El título de este resultado será “Cuenta objetivo cartesiano”. • Visualizar la mayor edad de los empleados cuya oficina esté en la zona este o en la ciudad de A Coruña. • Se pretende obtener la media de las diferencias entre ventas y cuotas. SELECT count(DISTINCT Matricula) AS “Número de vehículos” FROM REPARACIONES WHERE FechaEntrada BETWEEN “2011-01-01” AND “2011-01-31”. • Visualizar la media de los importes asociados al producto bisagra. ordenadas por marca y contar visualmente cuántas filas había por cada marca. La siguiente imagen muestra una consulta agrupada: Si queremos saber. 9. El título de esta columna será “Aportación media empleados”. 3. y obtener subtotales. saber cuántos vehículos de cada marca visitan el taller podría resultar interesante a la hora de especializar a los mecánicos en determinados motores. Este resultado aparecerá con el título “Media de mayores”. para establecer condiciones de búsqueda para grupos de filas se utiliza HAVING. • Obtener la media. Es el momento de recurrir a la cláusula GROUP BY. SELECT SUM(importe). la segunda columna no está permitida. con el nombre de la marca y el número de vehículos de esa marca que nos han visitado. A continuación podemos observar dos consultas agrupadas. Seguidamente queremos obtener las oficinas con un promedio de ventas de sus empleados mayor que 500000. Ahora se escribe la consulta agrupada del apartado anterior. ya que la lista de selección contiene elementos válidos. La consulta devolverá una fila por cada marca distinta. La cláusula HAVING se emplea para evaluar condiciones sobre las filas que devuelve GROUP BY.UT_4 GBD SELECT Marca FROM VEHICULOS ORDER BY Marca.… FROM NombreTabla [WHERE Condiciones…. • Sumar totales sobre grupos de elementos. oficina FROM empleados GROUP BY oficina HAVING AVG(ventas) > 500000 En la condición que aparece detrás de la cláusula HAVING sólo pueden aparecer : o o o valores constantes funciones de columna columnas de agrupación (columnas que aparecen en la cláusula GROUP BY) 23 . SELECT SUM(ventas). rep*10 FROM pedidos GROUP BY rep*10 SELECT SUM(importe). El listado estará ordenado por marcas. Función. La primera es válida. La sintaxis de estas consultas es la siguiente: SELECT NombreColumna. count(*) AS ‘Número de vehículos’ FROM VEHICULOS GROUP BY Marca ORDER BY Marca. SELECT Marca. valores máximos.….] GROUP BY NombreColumaDeGrupo [HAVING Condiciones] [ORDER BY Criterio] Estas cláusulas combinadas con funciones de resumen nos permiten: • Contar grupos de elementos.. count(*) AS ‘Numero de vehiculos’ FROM VEHICULOS GROUP BY Marca HAVING count(*)>2 ORDER BY Marca. En la lista de selección de una consulta agrupada sólo pueden aparecer: o o o o valores constantes funciones de columna columnas de agrupación (columnas que aparecen en la cláusula GROUP BY) cualquier expresión basada en las anteriores. etc. ¿Y si la tabla tuviera miles de filas? No podríamos hacerlo así. ya que el campo rep es una columna simple que no está encerrada en una función de columna. pero únicamente nos mostrará las marcas para las que el número de vehículos que han visitado nuestro taller sea mayor de 5: SELECT Marca. rep FROM pedidos GROUP BY rep*10 Del mismo modo que para establecer condiciones de búsqueda para filas individuales se utiliza WHERE. Sin embargo. Tanto GROUP BY como HAVING se usan en consultas agrupadas. Seguidamente se obtiene un listado con dos columnas: la marca y el número de vehículos que visitan nuestro taller. ni está en la lista de columnas de agrupación. Realizan WHERE ACTUACIONES. la cuota máxima de venta de uno de sus trabajadores. • El número de pedidos en los que se ha visto involucrado cada artículo. • Para cada grupo de empleados que tienen el mismo jefe se obtendrá la media de sus cuotas. El resultado debe incluir la cuota.Referencia = Realizan. • La suma de las unidades vendidas de productos de un determinado fabricante. Ejercicio resuelto Obtener la media de horas empleadas en cada tipo de actuación. Implementa otra versión que además incluya el nombre del jefe. No se tendrán en cuenta los pedidos cuyo representante pertenezca a una oficina del oeste.Referencia GROUP BY ACTUACIONES. Ejercicio: HAVING. SELECT Descripcion. Ejercicio: GROUP BY Realiza las siguientes consultas sobre la base de datos bdempleados: • La edad media de los trabajadores que tienen el mismo cargo. Solution: SELECT Descripcion. En la salida se incluirá el código del cliente. Se incluirá el código del jefe. Se incluirá el cargo en la salida. • El importe máximo que se ha vendido a cada cliente. No se incluirán en dichas medias las cuotas de empleados que tengan como jefe a uno cuya cuota sea menor de 300000. Se incluirá en el resultado el código de cada oficina. Se incluirá en la salida el código del producto. la mayor edad de los empleados que lo vendieron. • El importe total de cada producto vendido a partir de 2010.Referencia = Realizan. Se incluirá en el resultado el código del producto.Referencia HAVING AVG(Horas) >= 1. • Para cada producto. Sólo se tendrán en cuenta los clientes que tengan asignado un representante mayor de 40 años.Referencia GROUP BY ACTUACIONES. • De entre los empleados que tienen el mismo jefe se obtendrá la cuota máxima. Se incluirá en el resultado el código del producto.UT_4 GBD o cualquier expresión basada en las anteriores. • Para cada producto. Realizan WHERE ACTUACIONES. • La fecha del contrato más antiguo de los empleados de cada oficina. el mayor objetivo de las oficinas de los empleados que lo vendieron. AVG(Horas) AS “Horas por término medio” FROM ACTUACIONES. • Para cada grupo de empleados que tengan la misma cuota se calculará la fecha de contrato más antigua y más moderna. • Para cada región. mostrando únicamente aquéllas cuya media no sea inferior a una hora. Se incluirá el código del jefe. No se 24 . Realiza las siguientes consultas sobre la base de datos bdempleados: • La suma de las ventas de los empleados de cada oficina. Sólo se tendrán en cuenta los artículos cuyo precio sea mayor que 200 y menor que 2000. AVG(Horas) AS “Horas por término medio” FROM ACTUACIONES. En la salida se incluirá el código del cliente. Se incluirá el número de cada oficina.Referencia HAVING AVG(Horas) >= 1. No se incluirán en el resultado las oficinas cuyas ventas totales sean menores de 200000 ni los empleados cuya oficina sea la 13. Se incluirá en el resultado el código del jefe. • El importe medio que se ha vendido a cada cliente que tenga un límite de crédito inferior a 50000. No se tendrán en cuenta para calcular el resultado a los empleados cuya edad sea menor de 35. • El número de empleados que tiene a su cargo cada empleado que es jefe. • Sobre el resultado final no se pueden aplicar otras cláusulas como GROUP BY..Unión de consultas. No se tendrán en cuenta los clientes cuyo límite de crédito sea inferior a 30000. La sintaxis para realizar una UNION es: SELECT…. 10. únicamente puede contener ORDER BY al final de la sentencia SELECT. y éstas son del mismo tipo..WHERE…. Ejercicio: UNION. el identificador de columna de la tabla que está a la izquierda del operador UNION. sólo aparece una fila en el resultado de la consulta y no dos repetidas. etc. UNION [ALL | DISTINCT] SELECT……. SELECT * FROM FACTURAS_2013 WHERE FechaFactura BETWEEN ‘2013-01-01’ AND ‘201301-31’ UNION SELECT * FROM FACTURAS_2014 WHERE FechaFactura BETWEEN ‘2014-0101’ AND ‘2014-01-31’. ordenar el resultado. El resultado es una tabla con las filas de la primera tabla y las filas de la segunda. FROM……. No se quieren en la salida los datos de los clientes cuyo promedio del límite de crédito sea inferior que 50000.. Realizar una consulta de unión entre las facturas de ambas tablas correspondientes al mes de enero. el resultado de la consulta. Las condiciones en las que se establece una consulta de unión son: • Las consultas unidas deben tener el mismo número de columnas • Las columnas tendrán como encabezado.. El resultado podrá incluir tuplas repetidas. no unir todas las columnas de las tablas. Esta operación se realiza sobre dos tablas o consultas que tienen el mismo número de columnas. junto con la oficina. la ciudad. Ejercicio resuelto Supongamos que tenemos dos tablas de FACTURAS: Una denominada FACTURAS_2013 con las facturas emitidas ese año y otra FACTURAS_2014 con las facturas emitidas en este año. Por otra parte no se incluirán las oficinas de la zona norte y centro. mediante una única consulta la oficina. (UNION DISTINCT) • Se puede hacer que las filas repetidas aparezcan en el resultado de la consulta usando UNION ALL. Los registros del resultado deberán 25 . Se pretende seleccionar. el objetivo de ventas y las ventas de cada oficina.FROM…. Si no se especifica ALL o DISTINCT por defecto se usa DISTINCT. • Si en las tablas unidas hay filas que contienen la misma información. de la base de datos bdempleados. Solution: SELECT * FROM FACTURAS_2013 WHERE FechaFactura BETWEEN ‘2013-01-01’ AND ‘201301-31’ UNION SELECT * FROM FACTURAS_2014 WHERE FechaFactura BETWEEN ‘2014-0101’ AND ‘2014-01-31’. • Se pueden establecer criterios o condiciones para la unión. Sólo se incluirán en el resultado a los empleados cuyo contrato sea posterior a 1986.UT_4 GBD incluirán en el resultado final aquellas filas cuya suma de unidades al cuadrado sea menor de 1000. • El promedio del límite de crédito para los clientes asignados a cada empleado. Se incluirá en el resultado el código del representante del cliente. el nombre de los empleados.WHERE…. El resultado aparecerá ordenado por el promedio. sus cuotas de venta y sus ventas. IdFactura FROM CLIENTES INNER JOIN FACTURAS ON CLIENTES. 11.. Reflexiona Compara las siguientes alternativas para definir combinaciones internas: a.IdReparacion. A continuación se combinan 3 tablas para obtener el importe total (suma de unidades*precio) de los recambios sustituidos en cada reparación: SELECT REPARACIONES. de otra forma: SELECT Nombre.CodCliente.IdReparacion) INNER JOIN RECAMBIOS ON Incluyen. Apellidos.. Estas composiciones se denominan internas porque en el resultado no aparece ninguna fila de una tabla que no tenga correspondencia con las filas de la tabla con la que se combina. b. igualmente equivalentes. SELECT …. SELECT …. En estas se combina información procedente de dos o más tablas. En la salida de la siguiente consulta sólo aparecen los datos de los clientes que tengan alguna factura registrada. SELECT … FROM NombreTabla1 JOIN NombreTabla2 WHERE condición de relación.IdRecambio=RECAMBIOS. sum(Unidades * PrecioReferencia) AS 'Importe recambios' FROM REPARACIONES INNER JOIN INCLUYEN ON REPARACIONES..FROM NombreTabla1 INNER JOIN NombreTabla2 USING(ColumnaRelacionada) ¿Por qué podemos considerar que la sintaxis empleada en la opción b es más restrictiva que la de la opción a? 26 . NombreTabla2 WHERE condición de relación. Otras sintaxis de combinación interna. Las sintaxis de las combinaciones internas que vemos a continuación son equivalentes: SELECT … FROM NombreTabla1 .. SELECT … FROM NombreTabla1 INNER JOIN NombreTabla2 ON condición de relación..IdRecambio GROUP BY IdReparacion. si existiesen códigos repetidos. Apellidos. SELECT … FROM NombreTabla1 INNER JOIN NombreTabla2 ON condición de relación. Las combinaciones de tablas que hemos visto hasta ahora en consultas multitabla son “Composiciones o combinaciones internas”. éstos se ordenarían por el segundo campo (nombre o ciudad). IdFactura FROM CLIENTES INNER JOIN FACTURAS USING(CodCliente).FROM NombreTabla1 INNER JOIN NombreTabla2 USING(ColumnaRelacionada). Para los clientes con varias facturas su nombre y apellidos se repite: SELECT Nombre..CodCliente = FACTURAS. son: SELECT … FROM NombreTabla1 JOIN NombreTabla2 ON condición de relación.UT_4 GBD aparecer ordenados por el código de la oficina y.Combinaciones internas..IdReparacion=Incluyen. Los clientes que no tengan facturas no aparecen. formando filas relacionadas según la condición de búsqueda establecida con WHERE que generalmente es la clave principal de una tabla y la clave ajena relacionada en la otra tabla. . • Selecciona todos los campos de la tabla clientes junto a los datos de los pedidos que han realizado. • Seleccionar el número de cada pedido. y para establecer una relación las columnas deben tener el mismo tipo de datos y tamaño. La combinación externa puede expresarse de dos formas: • Combinación externa a la izquierda: LEFT JOIN. su límite de crédito.. Ejercicio: INNER JOIN Realiza las siguientes consultas sobre la base de datos bdempleados. añade una fila al resultado con los valores de las columnas de la primera tabla (izquierda) y NULL para todas las columnas de la segunda que no han encontrado resultados coincidentes. La sintaxis equivalente en ambos casos para LEFT JOIN: SELECT …. Es una variedad de composición de tablas que permite seleccionar algunas filas de una tabla aunque éstas no tengan correspondencia con las filas de la otra tabla con la que se combina. • Seleccionar el nombre de empleado (con el título “Nombre de empleado”). así como el nombre del jefe del empleado (con el título “Nombre del jefe”). La sintaxis equivalente en ambos casos para RIGHT JOIN: 27 . el código de su oficina. y para establecer una relación las columnas deben tener el mismo tipo de datos y tamaño. así como la ciudad en la que se encuentra la oficina del representante que tiene asignado. Cada fila de la tabla colocada a la izquierda que no se pueda combinar con ninguna fila de la segunda tabla. Cada fila de la tabla colocada a la derecha que no se pueda combinar con ninguna fila de la primera tabla. No se incluirán en el resultado los datos de pedidos cuyo importe sea inferior a 40000 o superior a 60000.UT_4 GBD Porque para relacionar las tablas con USING la columna por la cual se establece la combinación se tiene que llamar igual en ambas tablas. Retroalimentación: Porque para relacionar las tablas con USING la columna por la cual se establece la combinación se tiene que llamar igual en ambas tablas.FROM NombreTabla1 LEFT JOIN NombreTabla2 ON condición de relación. • Seleccionar el nombre de cliente. Cuando no existe correspondencia en la segunda tabla se combina con NULL. pero pueden tener distinto nombre de columna.FROM NombreTabla1 LEFT OUTER JOIN NombreTabla2 ON condición de relación. la fecha de su contrato. añade una fila al resultado con los valores de las columnas de la segunda tabla (derecha) y NULL para todas las columnas de la primera que no encuentren coincidencias. el nombre de la provincia de la oficina. 12.. Sólo se incluirán en el resultado a los clientes cuyo límite de crédito sea mayor que 40000. usando INNER JOIN: • Selecciona todos los campos de la tabla clientes junto a los datos de los pedidos que han realizado. • Combinación externa a la derecha: RIGHT JOIN. así como el nombre de su representante y la región a la que pertenece la oficina de éste. pero pueden tener distinto nombre de columna.FROM NombreTabla1 LEFT JOIN NombreTabla2 USING(ColumnaRelacionada)… SELECT ….Combinaciones externas. incluyéndose únicamente la fecha de cada pedido y el importe total. su fecha y su importe. SELECT …. IdFactura FROM CLIENTES RIGHT JOIN FACTURAS ON CLIENTES.Matricula WHERE Avería IS NULL.Matricula = REPARACIONES.Matricula. Ejercicio resuelto Obtener un listado de los vehículos registrados en nuestra base de datos que no hayan sufrido reparaciones.. Avería FROM VEHICULOS LEFT JOIN REPARACIONES ON VEHICULOS. Ejercicio: LEFT JOIN/RIGHT JOIN Realiza las siguientes combinaciones sobre la base de datos bdempleados. En este caso el resultado mostraría el número de las facturas aunque no existiera ningún cliente relacionado. usando siempre el operador de combinación más apropiado: • Se pretende obtener una relación en la que aparezcan los datos de todas las oficinas junto a los nombres y las edades de los directores de cada una de ellas (si una oficina no tiene director entonces los datos de este aparecerán en blanco). Color.Matricula = REPARACIONES.Matricula.CodCliente. este caso no podría darse puesto que hemos exigido en la definición de la relación que no pueda haber ninguna factura que no esté asociada a ningún cliente (Integridad referencial): SELECT Nombre. SELECT VEHICULOS.FROM NombreTabla1 RIGHT JOIN NombreTabla2 ON condición de relación. Solution: SELECT VEHICULOS. Apellidos. Aparecerán los datos de todas las oficinas. En realidad. Marca.CodCliente = FACTURAS. Modelo.Matricula WHERE Avería IS NULL. • Obtener una relación que contenga por un lado los nombres y títulos de los empleados. IdFactura FROM CLIENTES LEFT JOIN FACTURAS ON CLIENTES. Avería FROM VEHICULOS LEFT JOIN REPARACIONES ON VEHICULOS..CodCliente. Marca. 28 . aunque estos últimos no tengan jefe. aunque tengamos algún cliente al que no le hayamos girado aún ninguna factura se mostrará su nombre y apellidos. Modelo.UT_4 GBD SELECT …. En el IdFactura aparecerá NULL: SELECT Nombre. En la siguiente consulta. • Se pretende obtener una relación en la que aparezcan los nombres de todos los empleados que son jefe junto con los nombres de todos los empleados. Color.FROM NombreTabla1 RIGHT JOIN NombreTabla2 USING(ColumnaRelacionada)… SELECT …. y además códigos y la ciudad de las oficinas de los mismos. SELECT …. Apellidos.FROM NombreTabla1 RIGHT OUTER JOIN NombreTabla2 ON condición de relación.CodCliente = FACTURAS. aunque estas no tengan empleados asignados. En las columnas nombre y apellidos mostraría NULL. además tiene algunas restricciones en cuanto a número de columnas según el lugar donde aparece en la consulta principal. escribiendo tras la cláusula WHERE otra sentencia SELECT.… WHERE Expresión OperadorRelacional (SELECT…. Se aconseja no utilizar campos calculados en las subconsultas. 29 . La sintaxis será: SELECT NombreColumna. ni puede ser la UNION de varias sentencias SELECT. FROM NombreTabla. cuyo importe esté por encima del importe medio. Una subconsulta tiene la misma sintaxis que una sentencia SELECT normal exceptuando que aparece encerrada entre paréntesis. INSERT. no puede contener la cláusula ORDER BY. parece que ya estamos listos para escribir cualquier tipo de consulta en SQL que nos permita acceder a la información almacenada. Supongamos que el Importe medio obtenido sea 100.…. Investigaremos con Alejandra si este tipo de consultas. Con lo que hemos visto hasta ahora necesitaríamos hacer dos consultas: • Obtener el importe medio de las actuaciones. En muchas ocasiones para realizar una consulta necesitaremos los datos devueltos por otra consulta. El tipo de dato de la expresión situada después de WHERE debe coincidir con el tipo de dato devuelto por la subconsulta.Subconsultas. Siguiendo los pasos de Alejandra. y cómo se utilizan.) En nuestro ejemplo sería: SELECT Descripcion FROM ACTUACIONES WHERE Importe > <br />(SELECT avg(Importe) FROM ACTUACIONES). • Obtener un listado con la descripción de las actuaciones cuyo importe sea mayor que el importe medio. Dentro de una consulta se pueden usar varias subconsultas enlazadas con el operador AND.UT_4 GBD 13. Para entender la necesidad de realizar una subconsulta veremos un ejemplo: supongamos que queremos obtener un listado con las actuaciones que se llevan a cabo en nuestro taller. Así el SELECT principal actúa sobre las filas devueltas por el SELECT anidado. están recogidas en el SQL de nuestro SGBD MySQL. ralentizan la consulta. Cuando se ejecuta una consulta que contiene una subconsulta.. Ahora haríamos la segunda consulta basada en el resultado anterior: SELECT Descripcion FROM ACTUACIONES WHERE Importe >100. pero no es así. la subconsulta se ejecuta por cada fila de la consulta principal. Estas restricciones las iremos describiendo en cada caso. Las subconsultas permiten escribir estas dos consultas en una. En primer lugar haríamos la primera consulta: SELECT AVG(Importe) FROM ACTUACIONES. UPDATE o CREATE. Las subconsultas se pueden usar dentro de otras sentencias como DELETE. denominadas subconsultas. numemp = pedidos. En el siguiente ejemplo. de otra subconsulta que a su vez forma parte de la consulta principal. pero más que subconsulta sería una consulta. Seguidamente se coge el segundo empleado y se calcula la subconsulta con numemp = 102 (numemp del segundo empleado).UT_4 GBD Las consultas que utilizan subconsultas suelen ser más fáciles de interpretar por el usuario. Una referencia externa es un nombre de columna que. el valor de la referencia externa irá cambiando. la subconsulta más interna se ejecutaría 2000 veces. Como la subconsulta se ejecuta por cada fila de la consulta principal. de lo contrario se genera error. Al final obtenemos una lista con el número. es decir. La consulta resulta también más difícil de leer. no se refiere a ninguna columna de las tablas designadas en la FROM de la subconsulta sino a una columna de las tablas designadas en la FROM de la consulta principal. nombre FROM empleados WHERE numemp = (SELECT DISTINCT rep FROM pedidos WHERE clie = (SELECT numclie FROM clientes WHERE nombre = 'Julia Antequera')) Cuando la subconsulta aparece en la lista de selección (véase ejemplo anterior) de la consulta principal no puede devolver varias filas ni varias columnas. nombre. El resultado del ejemplo anterior se puede obtener de la siguiente forma: SELECT numemp. nombre En la cláusula FROM se puede encontrar una sentencia SELECT encerrada entre paréntesis. Cuando se ejecuta la consulta anterior se coge el primer empleado y se calcula la subconsulta sustituyendo numemp por el valor que tiene en el primer empleado. Las subconsultas pueden anidarse de forma que una subconsulta aparezca en la cláusula WHERE. comprender y mantener cuando contiene más de uno o dos niveles de subconsultas. ese nombre de columna se denomina referencia externa. Muchos SQLs no permiten que una subconsulta aparezca en la lista de selección de la consulta principal. que es un campo de la tabla empleados. nombre y fecha del primer pedido de cada empleado. ya que normalmente se puede obtener lo mismo utilizando como origen de datos las dos tablas. su resultado se combina con las filas de la otra tabla para formar las filas origen de la SELECT primera y no admite referencias externas. A menudo. numemp.rep GROUP BY numemp. ya que no se ejecuta para cada fila de la tabla origen sino que se ejecuta una sola vez al principio. pero eso no supone ningún problema. dentro del cuerpo de una subconsulta. una consulta consume mucho más tiempo y memoria cuando se incrementa el número de niveles de anidamiento. se calcula la subconsulta de clientes. estando en la subconsulta. y así sucesivamente hasta llegar al último empleado. Se suelen utilizar subconsultas en las cláusulas WHERE o HAVING cuando los datos que queremos visualizar están en una tabla pero para seleccionar las filas de esa tabla necesitamos comprobar el valor de un dato que está en otra tabla. (SELECT MIN(fechapedido) FROM pedidos WHERE rep= numemp) FROM empleados. Si quitamos la cláusula WHERE de la subconsulta obtenemos la fecha del primer pedido de todos los pedidos no del empleado correspondiente. En este caso la subconsulta actúa de 30 . En la siguiente consulta se observa una subconsulta que contiene una referencia externa. y esto se repite por cada empleado. En la práctica. de la tabla origen de la consulta principal. por cada línea de pedido. nombre. MIN(fechapedido) FROM empleados LEFT JOIN pedidos ON empleados. hacer referencia al valor de una columna en la fila actual de la consulta principal. en el caso de tener 10 filas de empleados y 200 filas de pedidos. por ejemplo. de este modo la subconsulta obtiene la fecha más antigua en los pedidos del representante 101. el 101. es necesario. SELECT numemp. SELECT numemp. Nombre FROM EMPLEADOS WHERE CodEmpleado NOT IN (SELECT CodEmpleado FROM Intervienen. En el resultado no aparecerán los datos de un fabricante cuya media de precios de productos sea menor que la treintava parte de la media de precios de los productos vendidos en 2010. Utiliza subconsultas para obtener los siguientes resultados de la base de datos bdempleados: • Las ciudades de las oficinas. En el resultado final no aparecerán las descripciones de los productos cuyo mayor precio sea inferior al menor importe de todos los pedidos cuyo importe sea mayor de 100. En este ejemplo listamos el número y nombre de los empleados cuya fecha de contrato sea igual a la primera fecha de todos los pedidos de la empresa. junto con la cuota del empleado que hizo el pedido. REPARACIONES WHERE REPARACIONES. Utiliza subconsultas para obtener los siguientes resultados de la base de datos bdempleados: • Los códigos y nombres de la ciudad de todas las oficinas junto a la cantidad máxima de ventas de uno de sus trabajadores. • La descripción de todos los productos así como el mayor precio del producto asociado a dicha descripción. Solution: SELECT Apellidos. Nombre FROM EMPLEADOS WHERE CodEmpleado NOT IN (SELECT CodEmpleado FROM Intervienen. • Los nombres de los empleados que sean representantes cuyas ventas supongan al menos el 15% del total de ventas de todas las oficinas de las regiones este y centro juntas.IdReparacion = Intervienen. • Los códigos y números de todos los pedidos cuyo importe sea mayor de 20000. Ejercicio resuelto Obtener los nombres de los empleados que no hayan intervenido en reparaciones desde Enero. • Las descripciones de los productos junto al total de unidades vendidas y la media de los importes vendidos del mismo. Ejercicio: Subconsultas en las cláusulas WHERE y HAVING.IdReparacion = Intervienen.UT_4 GBD operando dentro de la condición. 31 . • Cada fabricante y la media del precio de sus productos. Ejercicio: Subconsultas en la lista de selección. además resulta más difícil de leer y de mantener cuando contiene más de dos niveles de anidamiento. El resultado final aparecerá ordenado por las descripciones de los productos. los nombres de los empleados y sus fechas de contrato. SELECT Apellidos. descartando los productos para los que las existencias sean menores que 20. de todos los empleados cuyas ventas multiplicadas por dos sean mayores que la media de ventas de todas las oficinas que tengan unas ventas mayores de 600000. REPARACIONES WHERE REPARACIONES.IdReparacion AND FechaSalida>=’2011-01-01’). para los que su límite de crédito sea mayor que la media de los importes de las tres primeras líneas de la tabla pedido. SELECT numemp.IdReparacion AND FechaSalida>=’2011-01-01’). • Los nombres de los clientes y de sus empleados asignados. En el resultado los registros aparecerán ordenados por el nombre de los clientes. nombre FROM empleados WHERE contrato = (SELECT MIN (fechapedido) FROM pedidos) Reflexiona En la práctica una consulta consume mucho más tiempo y memoria cuando se incrementa el número de niveles de anidamiento. En este caso la subconsulta devuelve una única columna y una única fila (es un consulta de resumen): SELECT oficina.. el test devuelve el valor nulo. si no se produce un error. 3. Si la subconsulta no produce ninguna fila o devuelve el valor nulo.1. Estos test son: 1. el test ANY devuelve el resultado verdadero. Si alguna de las comparaciones individuales produce el resultado verdadero. Test de pertenencia a un conjunto. Compara el valor de la expresión con cada uno de los valores producidos por la subconsulta. Tenemos el test ANY (algún. SQL devuelve una condición de error. Test de existencia.oficina) 2. La subconsulta debe devolver una única columna. 1. Existen cuatro tests de comprobación de condiciones muy útiles cuando trabajamos con subconsultas. La sintaxis es la siguiente: En el siguiente ejemplo se listan las oficinas cuyo objetivo sea superior a la suma de las ventas de sus empleados.Tests de comparación con subconsultas. ciudad FROM oficinas WHERE objetivo > (SELECT SUM(ventas) FROM empleados WHERE empleados. Test de comparación simple. La sintaxis es la siguiente: Con el test ANY se evalúa la comparación con cada valor devuelto por la subconsulta. si no se produce un error.oficina = oficinas. Test de comparación con subconsulta. Test de comparación cuantificada. el test ANY 32 .UT_4 GBD 13. Si la subconsulta no devuelve ningún valor. 2. si la subconsulta produce varias filas. alguno en inglés) y el test ALL (todos en inglés). La subconsulta debe devolver una única columna. Test de comparación cuantificada. 4. Se utiliza para comparar un valor de la fila que se está examinado con un único valor producido por la subconsulta. para todos los clientes que tengan un límite de crédito al menos 40 veces mayor que el importe de cada una de las líneas de pedido que hizo. SELECT oficina.UT_4 GBD devuelve falso. el test da falso. y es nulo para al menos alguno de los valores. • El código y ciudad de las oficinas. Si el test de comparación es falso para algún valor de la columna. cuales son los que realmente cumplen la condición que se indica. • Los nombres de los empleados para los que el doble de sus ventas sea mayor que las ventas asociadas a cada una de las oficinas del este. para todos aquellos pedidos cuyo representante tenga jefe o tenga una cuota mayor que 300000. Se listarán en el resultado las oficinas cuyo objetivo sea superior a alguna de las sumas obtenidas. SELECT oficina. Utiliza subconsultas para obtener los siguientes resultados de la base de datos bdempleados: • Los nombres y títulos de los empleados para los que el 50% de su cuota sea mayor que las ventas asociadas a alguna de las oficinas del centro o del oeste. ANY devuelve nulo. Si todas las comparaciones individuales producen un resultado verdadero. para todos aquellos productos para los cuales la décima parte de sus existencias sea mayor que la cantidad incluida en todas y cada una de sus líneas de pedido (una a una. ¿Por qué se cuelan en el resultado tantos registros? • El código de los pedidos y los nombres de los clientes que lo hicieron. Si el test de comparación es falso para todos los valores de la columna. Test de pertenencia a conjunto (IN/NOT IN). así como los nombres y edades de los jefes de los directores de las mismas. Si la subconsulta no produce ninguna fila. La siguiente subconsulta devuelve una única columna con las sumas de las cuotas de los empleados de cada oficina. sin sumarlas). Si la subconsulta no devuelve ningún valor el test ALL devuelve el valor verdadero. La siguiente subconsulta obtiene la lista de los números de oficina del este. el test ALL devuelve valor nulo. manualmente. Por lo tanto se listan los empleados de las oficinas del este. La subconsulta debe generar una única columna y las filas que sean. ciudad FROM oficinas WHERE objetivo > ALL (SELECT SUM(cuota) <br />FROM empleados GROUP BY oficina). pero es nulo para alguno de esos valores. 3. En el resultado sólo se incluirán los datos de las oficinas que tienen un director cuyo jefe haya hecho algún pedido de los productos 2a44l o 41002 o xk47. mientras que la consulta principal obtiene los empleados cuyo número de oficina sea uno de los números de oficina del este. ciudad FROM oficinas WHERE objetivo > ANY (SELECT SUM(cuota) <br />FROM empleados GROUP BY oficina). Este test examina si el valor de la expresión es igual a uno de los valores incluidos en la lista de valores producida por la subconsulta. A continuación se listan las oficinas cuyo objetivo sea superior a todas las sumas. • Los nombres de los empleados para los que la diferencia entre sus cuotas y sus ventas sea mayor que el 20% de los objetivos de cada una de las oficinas del este y mayor que el 10% de las ventas de todas y cada una de las oficinas del oeste. Si el test de comparación no es falso para ningún valor de la columna. el test devuelve el valor verdadero. • Los identificadores de los productos así como su descripción. ANY devuelve falso. Con el test ALL se evalúa la comparación con cada valor devuelto por la subconsulta. Ejercicio: ANY y ALL. • El nombre de los clientes y los nombres de sus representantes y sus edades. 33 . Analiza el resultado y determina. el resultado es falso. Si el test de comparación no es verdadero para ningún valor de la columna. El test EXISTS examina si la subconsulta produce alguna fila de resultados. el test toma el valor falso.oficina) Cuando se trabaja con tablas muy voluminosas el test EXISTS suele dar mejor rendimiento que el test IN. En la mayoría de los casos. la de la referencia externa para que la oficina que se compare sea la oficina del empleado. El test de existencia (EXISTS/NOT EXISTS). oficina FROM empleado WHERE oficina IN (SELECT oficina FROM oficinas WHERE region = 'este'). nunca puede tomar el valor nulo. SELECT numemp. • Los nombres de los clientes y su límite de crédito. habrá que utilizar una referencia externa. nombre. Con este test la subconsulta puede tener varias columnas. para todos aquellos productos para los cuales la cuarta parte de sus existencias sean mayor que la cantidad incluida en todas y cada una de sus líneas de pedido. es irrelevante. Ejercicio: IN/EXISTS Utiliza subconsultas para obtener los siguientes resultados de la base de datos bdempleados: • Se piden los identificadores de los productos así como su descripción. 4. para todos los clientes que tengan un representante que pertenezca a una oficina que tenga objetivo y venta mayores que cero (cuidado con los nulos). oficina FROM empleado WHERE EXISTS (SELECT * FROM oficinas WHERE region = 'este' AND empleados. 34 . En la subconsulta se pueden poner las columnas que queramos en la lista de selección (hemos utilizado el *). ya que el test se fija no en los valores devueltos sino en si hay o no filas en la tabla resultado de la subconsulta. el test adopta el valor verdadero. para todas las líneas de pedido hechas sobre un producto cuyas existencias sean mayores de 20. Si no se utiliza una referencia externa la subconsulta devuelta siempre será la misma para todas las filas de la consulta principal y en este caso se seleccionan todas las filas de la consulta principal (si la subconsulta genera filas) o ninguna (si la subconsulta no devuelve ninguna fila). pero saldrán los datos de aquellos productos que tengan asociada al menos una línea de pedidos. Observa que delante de EXISTS no va ningún nombre de columna. • Los códigos y números de pedido.UT_4 GBD SELECT numemp. • La descripción de los artículos y su código. cuando se utiliza el test de existencia. Si la subconsulta contiene filas. así como el nombre del empleado que los hizo y la ciudad de su oficina. A continuación se obtiene el mismo resultado que el ejemplo del test IN. nombre. para los que se hayan hecho pedidos con un importe mayor que 20000 y una cantidad mayor que 8 en una sola línea de pedido. Hemos añadido una condición adicional al WHERE.oficina = oficinas. si la subconsulta no contiene ninguna fila. …) LEAST(valor1. Si “expr1” es NULL. cad2) Devuelve “cad1” concatenada con “cad2”. valor2. cad2) RPAD (cad1. Devuelve la raíz cuadrada de “n”. cad2) LTRIM (cad) RTRIM (cad) SUBSTR (cad. El valor absoluto es siempre un número positivo. Si se omite “m”. devuelve “número” con 0 decimales. la función devuelve “expr2”. Devuelve la subcadena de “cad”. Devuelve la hora como un entero entre 0 y 59.Resumen de las funciones más frecuentes en MySQL Funciones aritméticas: ABS (n) MOD (m. todas las veces que aparezca. cad2) LOWER (cad) UPPER (cad) LPAD (cad1. cadena_sustitución) LENGTH (cad) INSTR (cad1. Suprime los blancos a la izquierda (LTRIM) o a la derecha (RTRIM) de una cadena. Devuelve el nombre del mes de la fecha dada. Devuelve el número de días transcurridos desde el año 0. Si se omite “n” devuelve todos los caracteres a partir de “m”. n DAY. LPAD() añade caracteres a la izquierda de “cad1” hasta que alcance la longitud “n” “cad2” es la cadena con la que re rellena por la izquierda (LPAD) o por la derecha (RPAD) “cad1” puede ser una columna de una tabla o cualquier literal. Devuelve “número” truncado a “m” decimales. n HOUR. Funciones de manejo de fechas y horas: CURTIME() CURRENT_TIME CURRENT_TIME() CURDATE() CURRENT_DATE CURRENT_DATE() SYSDATE() DAYNAME(fecha) DAYOFMONTH(fecha) MONTH(fecha) MONTHNAME(fecha) YEAR(fecha) HOUR(hora) MINUTE(hora) SECOND(hora) DATE_ADD(fecha. n) POWER (m. Si “expr1” no es NULL. m [. exponente) ROUND (número [. valor2. Devuelve el resto resultante de dividir ‘m’ entre ‘n’. …) IFNULL(expr1. m]) SQRT (n) TRUNCATE (número. m) Devuelve el valor absoluto de ‘n’. Devuelve el número del día del mes. El valor de “n” no puede ser negativo. n. Devuelve “cad” convertida a mayúsculas. Devuelve los segundos como un entero entre 0 y 59. n MONTH. Obtiene el menor valor de la lista. etc. Devuelve el resultado de añadir o restar a una fecha el intervalo de tiempo expresado como: n YEAR. Devuelve la cadena “cad” sustituyendo la “cadena_búsqueda” por la “cadena_sustitución”. n. cadena_búsqueda. Devuelve el valor de “numero” redondeado a “m” decimales. . Devuelve los minutos como un entero entre 0 y 59. devuelve “número” con 0 decimales y redondeado. expr2) Obtiene el mayor valor de la lista. Devuelve el valor de “m” elevado a un “exponente”. INTERVAL expr intervalo) TO_DAYS(fecha) Devuelve la hora actual en formato HH:MM:SS Devuelve la fecha actual en formato AAAA:MM:DD Devuelve una cadena con la fecha y hora actual: AAAA:MM:DD HH:MM:SS Devuelve el nombre del día de la semana. desde la posición indicada por “m” hasta tantos caracteres como indique “n”. Calcula la potencia de un número. Funciones de comparación: GREATEST(valor1. Devuelve la posición de la primera ocurrencia de “cad2” dentro de “cad1”. Devuelve el año de la fecha como un entero entre 1000 y 9999. Devuelve el número del mes de una fecha dada. la función devuelve “expr1”. Trunca los números para que tengan un determinado número de dígitos de precisión. Devuelve el número de caracteres de “cad”.n]) REPLACE (cad. Funciones de cadenas de caracteres: CONCAT (cad1. Si “m” es 0. Devuelve “cad” convertida a minúsculas. 4) AS 'Letras de las matrículas' FROM VEHICULOS.2) AS 'Dias transcurridos' FROM REPARACIONES. 8) Cuantos días. SELECT CONCAT(Nombre.0) AS 'Valor almacen' FROM RECAMBIOS. en mayúsculas. DATE_ADD(FechaSalida. 2) Obtener el nombre completo de los empleados del taller. 7) Mostrar la antigüedad de los empleados en años. 6) Mostrar los teléfonos de los clientes. 5) > RIGHT(CURDATE(). para el IdRecambio= 'RV_222_666'. Descripcion. ROUND((Stock*PrecioReferencia). SELECT CURDATE()-FechaSalida AS 'Dias transcurridos' FROM REPARACIONES WHERE Matricula='1515 DEF'. Orservar el resultado. de dos formas: a) Truncando el resultado: SELECT IdRecambio. SELECT Matricula. 4) ¿Cuántos días han transcurrido desde que salió del taller el vehículo de matrícula 1515 DEF. SELECT UPPER(CONCAT(Nombre. 5) A los 3 meses de retirar un coche llamamos al cliente para valorar su satisfacción. Mostrar únicamente 2 decimales? SELECT ROUND(AVG(TO_DAYS(FechaSalida)-TO_DAYS(FechaEntrada)). INTERVAL 3 MONTH) FROM REPARACIONES. Apellidos) AS 'Nombre del empleado'.' '. TRUNCATE(Stock*PrecioReferencia). 5)) AS 'Años de Antiguedad' FROM EMPLEADOS. por ejemplo. . b) Redondeando el resultado: SELECT IdRecambio.' '. SELECT SUBSTR(Matricula. Descripcion. En caso de que no tengan teléfono mostrar ‘sin teléfono’. Obtener un listado con las matriculas y las fechas en que haremos la llamada transcurridos esos 3 meses. 'Sin teléfono') FROM CLIENTES.5. 3) Extraer las letras de las matrículas de los vehículos. Apellidos)) FROM EMPLEADOS.0) AS 'Valor almacen' FROM RECAMBIOS. SELECT IFNULL(telefono. por término medio.Ejemplos: 1) Obtener el valor de los recambios que tenemos en el taller sin decimales. YEAR(CURDATE())-YEAR(FechaAlta)-(RIGHT(FechaAlta. está un coche en el taller.