You are on page 1of 35

Ing.

Alejandro Sueldo

Curso de SQL usando MySQL


Autor Carlos Zaltzman
viernes, 07 de abril de 2006
Modificado el domingo, 24 de febrero de 2008

En este artículo se explica el uso de la sentencia SELECT para realizar consultas a bases de datos MySQL. Se explican
muchos conceptos relacionados al uso de la sentencia SELECT, pero sobre todo, se incluyen una gran cantidad de
ejemplos y ejercicios.

Supongamos que usted ha instalado MySQL en una empresa. En ese caso los empleados tienen interés en poder
realizar consultas a la base de datos. Pasado un tiempo, a un nivel gerencial medio se desarrolla un considerable
interés en poder realizar consultas directamente. Es muy conveniente poder realizar consultas sin pasar por un
mecanismo burocrático o incurrir en mayores costos.

Este tutorial puede servir de base para un curso. En general, los estudiantes deberían tener alguna experiencia previa
como operadores. O quizás usted desarrolla aplicaciones y se encuentra con MySQL instalado. Quiere aprender
rápidamente (por ejemplo, en un día) a realizar consultas en mysql, con peculiar atención a los problemitas que se
generan con relación a los tildes, los formatos de fecha, etc.

En estos casos, confiamos en que este tutorial le resulte de ayuda.

Suponemos que tenemos a disposición un servidor MySQL versión 4.1.3b-beta o posterior. Versiones anteriores pueden
servir para casi todo el curso, pero en algunas pueden no funcionar los subqueries.

- Índice

- Conociendo la base de datos.

- Instrucciones SELECT elementales.

- Manejo de fechas.

- Funciones de agregados. (Aggregate functions).

- Agrupando datos.

- Vinculaciones entre tablas.

- Búsqueda elemental de texto.

- Unión de dos tablas de resultados.

- Subqueries.

- Salida a Excel.

- El funcionamiento de SELECT.

- Glosario.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

- Bibliografía.

El proceso por el que normalmente se extrae información de una base de datos, en SQL, es la instrucción SELECT.
Veremos a continuación varios problemas, con sus soluciones, relativos a SELECT.

En estos problemas utilizaremos una base de datos llamada empresa. Se dispone de una instalación de la base de datos
para Windows. Baje el archivo crear_empresa.sql de aquí.

En lo que sigue suponemos que hay un directorio C:\mysql\bin donde tenemos el cliente mysql que se llama justamente
mysql.exe. Si no es así, tendremos que averiguar en qué directorio se encuentra, y en todo lo que sigue se deberá
sustituir C:\mysql\bin por el directorio donde se encuentra mysql.exe. Cree un directorio dentro del c:\mysql\bin con un
nombre corto. Para lo que sigue supondremos que dicho directorio es c:\mysql\bin\p.

Copie el archivo crear_empresa.sql a este directorio.

Asegúrese que el servidor MySQL funciona. Si usted está trabajando directamente en el equipo que tiene instalado el
servidor puede iniciarlo con el programa WinMySqlAdmin. Este programa se encuentra normalmente en el directorio
c:\mysql\bin. Por otra parte, si está accediendo a un servidor en red, supondremos que el servidor está funcionando.
De lo contrario deberá contactar al administrador de la red.

Ejecute el cliente mysql, según el siguientes procedimiento. En la mayoría de las instalaciones usted debería tener un
nombre de usuario y un password (clave). Basta que cree una ventana MS-DOS (busque MS-DOS, o Símbolo de
Sistema, en Inicio, Programas) y luego escriba
C:\WINDOWS > cd c:\mysql\bin C:\mysql\bin > mysql -uUsuario –pClave

donde Usuario debe sustituirse por su nombre de usuario y Clave por su clave. Si usted está accediendo desde el
equipo donde está instalado el servidor, probablemente no necesite usuario ni clave. En ese caso, ingrese simplemente
el comando mysql.
C:\MySQL\bin > mysql

Debería aparecer, después de algunos mensajes, un prompt como este:


mysql>

En ese prompt, escriba lo siguiente.


mysql>source p/crear_empresa.sql

En este momento debería crearse la base de datos. Ya está listo para comenzar el curso. Si tiene dificultades, es
posible que el administrador de base de datos no le haya dado suficientes "derechos". Quizás usted no tenga "derecho"
a crear una base de datos, por ejemplo. Contáctelo y solicítele poder crear y tener todos los derechos sobre la base
empresa.

Conociendo la base de datos


En primer lugar, antes de empezar a estudiar la instrucción SELECT exploraremos la base de datos. Suponemos que el
cliente mysql está funcionando y tenemos el prompt mysql> a la vista. Si no es así, ejecute el cliente mysql.

Para acceder a la base de datos utilizamos la sentencia USE.


mysql> USE empresa;

Recibimos un mensaje "Database changed" (base de datos cambiada). Una base de datos está formada por tablas,
muy semejantes a las tablas de cualquier libro.

Para ver qué tablas tenemos escribimos la sentencia SHOW TABLES.

mysql> SHOW TABLES; +-------------------+ | Tables_in_empresa | +-------------------+ | articulos | | clientes ||


conformes | | empleados | | facturas | | grupos | | lineas_factura | | sucursales | | ventas
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

| +-------------------+ 9 rows in set (0.00 sec)

Para ver qué contiene alguna de esas tablas escribimos nuestra primera instrucción SELECT :
mysql> SELECT * FROM sucursales; +----+-------------+ | id | descripcion | +----+-------------+ | 1 | Centro | | 2 | Unión
| | 3 | Malvín | +----+-------------+
Esta tabla está formada por dos columnas: Id y Descripcion. Los nombres de columnas tampoco pueden llevar tildes.
Debajo de los nombres están los valores. Tenemos una fila, por ejemplo, donde Id vale 2 y Descripcion es "Unión". Para
averiguar más sobre esta tabla escribimos:
mysql> DESCRIBE sucursales; +-------------+------------------+------+-----+---------+----------------+ | Field | Type |
Null | Key | Default | Extra | +-------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned
| | PRI | NULL | auto_increment | | descripcion | varchar(15) | | | | | +-------------+------------------
+------+-----+---------+----------------+

La instrucción "DESCRIBE sucursales" se podría traducir como "Realice una descripción de la tabla sucursales". Cada fila
es una descripción de la columna cuyo nombre figura a la izquierda. En este caso, la 2º fila describe Id y la 3ª describe
Descripcion. Esta descripción de la tabla sucursales contiene información más bien técnica, pero algunas partes son
importantes:

El varchar(15) que se encuentra en la 3ª fila, 2ºcolumna significa que la columna Descripcion puede tener un número
variable de caracteres, hasta 15. Análogamente el int(10) que se encuentra en la 2ª fila, 2ª columna indica que Id es un
número entero.

La palabra PRI que se encuentra en la 2ªfila, 4ª columna significa que Id caracteriza de manera única una fila. Es decir,
cada fila de sucursales va a tener un número que va a estar en la columna Id. Diferentes filas tendrán diferentes
números. De manera que un valor de Id, si está en la tabla, determina una fila. PRI es una abreviatura de PRIMARY
KEY , clave primaria. Esta es una expresión usada en computación para indicar una columna que se usa para identificar
las filas. Es algo así como el número de documento de identidad para las personas. Si se quiere hacer una referencia a
una sucursal en otra tabla se usa el Id.

Sugerimos que el estudiante explore, usando SELECT * FROM ... y DESCRIBE ..., sobre las diversas tablas de la base
de datos empresa.

Tipos de datos
En una tabla cada columna es de un tipo de datos. Para nuestros fines hay 3 grandes tipos de datos: numéricos,
cadenas de caracteres y fechas.

Los datos numéricos pueden ser enteros (int) o decimales (decimal). Los decimales tienen una parte entera y una
fraccionaria. Por ejemplo, un decimal puede valer 120.40.

Las cadenas de caracteres representan texto, generalmente con un largo variable, hasta un máximo dado. Pueden
contener letras, números y otros caracteres como ‘=’,’+’, etc.

Ya vimos un ejemplo con la columna Descripcion de la tabla sucursales. Las columnas de tipo fecha tienen, en su
descripción, la palabra "date". Cualquier columna puede, en principio, tomar el valor NULL, que representa un valor
desconocido o inexistente. Sin embargo, cuando se crearon las tablas el administrador de la base de datos
normalmente especificó que la mayoría de las columnas no pueden tomar valores NULL. Las que sí pueden aparecen con
la palabra YES en la columna NULL de la tabla que se obtiene haciendo el query "DESCRIBE nombre_de_tabla" .
Vemos que por ejemplo en la tabla Sucursales la base de datos no aceptará un valor NULL ni en Id ni en Descripcion.

Instrucciones SELECT elementales


La instrucción SELECT
Para extraer información de una base de datos, ingresamos un texto llamado "query" (pronúnciese "cueri") en el cliente
mysql. El query indica qué información queremos. El plural de "query" es "queries" (pronúnciese "cueris"). Se podría
traducir query como consulta, pero hemos preferido mantener el término técnico. La información sale a pantalla, en un
formato poco práctico cuando se manejan cantidadades importante de datos. En la sección 10 veremos cómo resolver
este problema.

Por ahora, todos nuestros ejemplos se llevan a la práctica de la misma forma.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

- El servidor MySQL debe estar en funcionamiento.

- Se debe haber iniciado el cliente mysql.

- Ya se ha seleccionado la base de datos empresa, con una instrucción "USE empresa".

- Se ingresa el query en el prompt mysql>.

- Los resultados salen a pantalla.

Para exhibir los valores de una columna determinada de una tabla, usamos SELECT Nombre_de_columna FROM
Nombre_de_tabla;

Ejemplo :
mysql> SELECT descripcion FROM sucursales; +-------------+ | descripcion | +-------------+ | Centro | | Unión | | Malvín
| +-------------+
Para seleccionar más de una columna, SELECT Nombre_de_columna_1, Nombre_de_columna_2,... FROM
Nombre_de_tabla;

Ejemplo:
mysql> SELECT nombre, direccion FROM clientes; +-------------+---------------------+ | nombre | direccion | +---------
----+---------------------+ | Matt Design | NULL | | Diana Pérez | Brito del Pino 1120 | | John Smith | Zum Felde
2024 | +-------------+---------------------+
Para seleccionar todas las columnas de una tabla, SELECT * FROM Nombre_de_tabla;

Ejemplo:
mysql> SELECT * FROM ventas; +----+---------+----------+---------+----------+----------+----------+------------+ | id | cliente |
vendedor | importe | articulo | cantidad | sucursal | fecha | +----+---------+----------+---------+----------+----------+----------+----
--------+ | 1 | 1| 1 | 178.50 | 1| 1| 1 | 2004-10-01 | | 2 | 2| 1 | 195.00 | 2| 1|
2 | 2004-10-05 | | 3 | 3| 1 | 178.50 | 1| 1 | NULL | 2004-10-07 | | 4 | 1| 1 | 16.00 | 7|
2| 2 | 2004-11-01 | | 5 | 1| 2 | 220.00 | 3| 1| 1 | 2004-12-02 | | 6 | 1| 1 | 5.50 |
5| 1| 1 | 2004-10-02 | | 7 | 1| 2 | 11.00 | 5| 2| 1 | 2004-10-03 | | 8 | 1| 2|
5.50 | 5| 1| 1 | 2005-01-01 | | 9 | 2| 1 | 200.00 | 2| 1| 2 | 2004-10-12 | +----+---------+-
---------+---------+----------+----------+----------+------------+
Obsérvese que los clientes, vendedores, artículos y sucursales son identificados por su Id. El importe representa el total
de la venta, no el precio unitario. También se pueden hacer cálculos con una columna numérica.

Ejemplos:
mysql> SELECT importe, 0.10*importe FROM ventas; +---------+--------------+ | importe | 0.10*importe | +---------+-------------
-+ | 178.50 | 17.85 | | 195.00 | 19.50 | | 178.50 | 17.85 | | 16.00 | 1.60 | | 220.00 | 22.00 | |
5.50 | 0.55 | | 11.00 | 1.10 | | 5.50 | 0.55 | | 200.00 | 20.00 | +---------+--------------+
Se pueden agregar a la salida columnas constantes, que no tienen relación con las tablas

Ejemplo:
mysql> SELECT "Impuesto", 0.10*importe FROM ventas; +----------+--------------+ | Impuesto | 0.10*importe | +----------+-----
---------+ | Impuesto | 17.85 | | Impuesto | 19.50 | | Impuesto | 17.85 | | Impuesto | 1.60 | | Impuesto |
22.00 | | Impuesto | 0.55 | | Impuesto | 1.10 | | Impuesto | 0.55 | | Impuesto | 20.00 | +----------+-----------
---+
En general es deseable no tener títulos de columna complicados como "0.10*Importe". Para esos casos se usa la
instrucción AS ( que significa, entre otras cosas, "como").

Ejemplo:
mysql> SELECT 0.10*importe AS impuesto FROM ventas; +----------+ | impuesto | +----------+ | 17.85 | | 19.50 | |
17.85 | | 1.60 | | 22.00 | | 0.55 | | 1.10 | | 0.55 | | 20.00 | +----------+
Se puede solicitar que no haya repeticiones en las filas seleccionadas. Basta agregar DISTINCT después del SELECT.

Ejemplo:
mysql> SELECT DISTINCT cliente FROM ventas; +---------+ | cliente | +---------+ | 1|| 2|| 3 | +---------+
Los resultados de cálculos, si no se toma alguna medida al respecto, a veces salen con demasiados decimales. En
esos casos, conviene usar la función ROUND. Esta función redondea los números a la cantidad deseada de decimales
después del punto. Por ejemplo, ROUND(2.343,2) produce el resultado 2.34. Análogamente ROUND(2.347,2) produce
2.35, y ROUND(2.245,2) produce 2.34. Para redondear a un entero alcanza con escribir ROUND(número). Por ejemplo,
ROUND(2.345) produce 2.

Ejemplo:
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

mysql> SELECT ROUND(importe/3,2) FROM ventas; +--------------------+ | ROUND(importe/3,2) | +--------------------+ |


59.50 | | 65.00 | | 59.50 | | 5.33 | | 73.33 | | 1.83 | | 3.67 | |
1.83 | | 66.67 | +--------------------+
En el último punto hemos visto por primera vez una función. Una función consta de un nombre, seguido de paréntesis,
entre los cuales según los casos puede no haber nada, o haber una o más cantidades. La función realiza ciertos
cálculos con las cantidades y genera otra cantidad, llamada el valor de la función. Una consideración práctica es que no
se pueden dejar espacios entre el nombre de la función y el primer paréntesis después del mismo. Siempre escribiremos
paréntesis después del nombre de una función.

La cláusula WHERE.
Esta cláusula sirve para seleccionar filas, dentro de las columnas seleccionadas. WHERE significa "donde". Se pueden
seleccionar filas donde una columna tiene un valor determinado.

Ejemplo:
mysql> SELECT * FROM clientes WHERE id=1; +----+-------------+-----------+----------+ | id | nombre | direccion |
vendedor | +----+-------------+-----------+----------+ | 1 | Matt Design | NULL | 1 | +----+-------------+-----------+----------+
Se puede seleccionar filas donde una columna tiene un valor mayor (o menor) que uno dado.

Ejemplo:
mysql> SELECT * FROM clientes WHERE id < 3; +----+-------------+---------------------+----------+ | id | nombre | direccion
| vendedor | +----+-------------+---------------------+----------+ | 1 | Matt Design | NULL | 1 | | 2 | Diana
Pérez | Brito del Pino 1120 | NULL | +----+-------------+---------------------+----------+
Las igualdades y desigualdades también se aplican a cadenas de caracteres. Una cadena es menor que otra cuando es
previa en orden alfabético. Por ejemplo "azzl" < "baa" . No se distingue entre mayúsculas y minúsculas (aunque, si se
lo desea, es posible configurar el servidor MySQL para que sí distinga). Es decir, "A" < "b" < "c" < "D" y "a"="A".

Ejemplo:
mysql> SELECT * FROM clientes WHERE nombre < "i"; +----+-------------+---------------------+----------+ | id | nombre |
direccion | vendedor | +----+-------------+---------------------+----------+ | 2 | Diana Pérez | Brito del Pino 1120 | NULL
| +----+-------------+---------------------+----------+
Este SELECT listará los clientes con nombre empezando en una letra anterior a "i" en el alfabeto.

También se aplican a fechas la igualdad y desigualdad. Para referirse a una fecha, se le escribe como "Año con 4
cifras-Mes-Día". Por ejemplo, "2004-12-20" indica el 20 de Diciembre de 2004.

Ejemplo:
mysql> SELECT * FROM ventas WHERE fecha < '2004-12-20'; +----+---------+----------+---------+----------+----------+----------
+------------+ | id | cliente | vendedor | importe | articulo | cantidad | sucursal | fecha | +----+---------+----------+---------+------
----+----------+----------+------------+ | 1 | 1| 1 | 178.50 | 1| 1| 1 | 2004-10-01 | | 2 | 2| 1|
195.00 | 2| 1| 2 | 2004-10-05 | | 3 | 3| 1 | 178.50 | 1| 1 | NULL | 2004-10-07 | | 4 |
1| 1 | 16.00 | 7| 2| 2 | 2004-11-01 | | 5 | 1| 2 | 220.00 | 3| 1| 1 | 2004-12-02 | |
6| 1| 1 | 5.50 | 5| 1| 1 | 2004-10-02 | | 7 | 1| 2 | 11.00 | 5| 2| 1 | 2004-10-
03 | | 9 | 2| 1 | 200.00 | 2| 1| 2 | 2004-10-12 | +----+---------+----------+---------+----------+----------+-----
-----+------------+
Para determinar si un dato es NULL se usa la condición &lsquo;IS NULL&rsquo;. Para saber si no es NULL, se usa la
condición &lsquo;IS NOT NULL&rsquo;.

Ejemplo:
mysql> SELECT * FROM ventas WHERE sucursal IS NULL; +----+---------+----------+---------+----------+----------+----------+----
--------+ | id | cliente | vendedor | importe | articulo | cantidad | sucursal | fecha | +----+---------+----------+---------+----------
+----------+----------+------------+ | 3 | 3| 1 | 178.50 | 1| 1 | NULL | 2004-10-07 | +----+---------+----------+--
-------+----------+----------+----------+------------+
No debe usarse <>NULL. Produce resultados equivocados. Usar IS NOT NULL.

Llamamos condiciones simples a las siguientes

Expresión Significado

a=b
a es igual a b

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

a=b
a es igual a b

a <> b
a es distinto de b

a<b
a es menor que b

a>b
a es mayor que b

a <= b
a es menor o igual a b

a >= b
a es mayor o igual a b

a IS NULL
a es NULL

a IS NOT NULL
a no es NULL

Las cantidades a y b pueden ser números, cadenas de caracteres o fechas, en todos los casos. En una cláusula
WHERE se puede usar cualquier condición simple. La cláusula WHERE selecciona aquellas filas en que la condición es
verdadera.

Las condiciones simples pueden aparecer combinadas por operadores lógicos. Los operadores lógicos son AND, OR y
NOT. Aquí E y F representan condiciones.

ExpresiónSignificadoEs verdadera cuando ...

E AND F
EyF
E es verdadera y F es verdadera

E OR F
E o F o ambos
E es verdadera o F lo es o ambas

NOT E
No E
E es falsa

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

NOTA : El operador NOT requiere paréntesis. Es decir se debe escribir WHERE NOT (salario >50) mientras que es
incorrecto WHERE NOT salario > 50. Se entiende que buscamos filas con salarios no mayores que 50.

Ejemplos:

Listar los empleados cuya fecha de ingreso sea anterior al 2004, o cuyo salario sea mayor que 50 ( o ambas cosas).
mysql> SELECT * FROM empleados WHERE fecha_ingreso < '2004-1-' OR salario > 50; +----+-----------------+---------------
+---------+ | id | nombre | fecha_ingreso | salario | +----+-----------------+---------------+---------+ | 1 | Carlos Zaltzman |
1999-12-10 | 10000 | | 2 | Juan Fernández | 2000-01-03 | 12000 | +----+-----------------+---------------+---------+
Listar los clientes cuyos nombres empiecen con una letra entre &lsquo;c&rsquo; y &lsquo;l&rsquo;.
mysql> SELECT * FROM clientes WHERE "C" <= nombre AND nombre < "M"; +----+-------------+---------------------+----------
+ | id | nombre | direccion | vendedor | +----+-------------+---------------------+----------+ | 2 | Diana Pérez | Brito del
Pino 1120 | NULL | | 3 | John Smith | Zum Felde 2024 | 1 | +----+-------------+---------------------+----------+
Obsérvese que la condición apropiada para obtener los nombre que empiezan con &lsquo;l&rsquo; es nombre
<&rsquo;M&rsquo;. Si escribiésemos nombre < =&lsquo;L&rsquo; no obtendríamos un nombre como &lsquo;Luis
Zúñiga&rsquo; porque &lsquo;L&rsquo;<&rsquo;Luis Zúñiga&rsquo;. Se pueden usar incluso condiciones más
complicadas. Por ejemplo, supongamos que ahora queremos listar los empleados cuya fecha de ingreso es anterior al
2004, o cuyo salario sea mayor que 50, pero no ambas cosas a la vez. Entonces, debemos escribir :
mysql> SELECT * FROM empleados WHERE (fecha_ingreso < '2004-1-1' OR salario > 50) -> AND NOT
(fecha_ingreso < '2004-1-1' AND salario > 50); Empty set (0.00 sec)
El resultado es "Empty set", es decir, no hay filas que cumplan la condición. En el caso de condiciones más complicadas
se recomienda un amplio uso de paréntesis.

La cláusula ORDER BY
La cláusula ORDER BY produce una ordenación de las filas de salida del query. Se puede ordenar por una columna
seleccionada.
mysql> SELECT cliente, articulo FROM ventas ORDER BY cliente; +---------+----------+ | cliente | articulo | +---------+---------
-+ | 1| 1|| 1| 7|| 1| 3|| 1| 5|| 1| 5|| 1| 5|| 2| 2|| 2|
2|| 3| 1 | +---------+----------+
También se puede ordenar por varias columnas.
mysql> SELECT cliente, vendedor, articulo FROM ventas ORDER BY cliente, vendedor; +---------+----------+----------+ |
cliente | vendedor | articulo | +---------+----------+----------+ | 1| 1| 1|| 1| 1| 7|| 1| 1|
5|| 1| 2| 3|| 1| 2| 5|| 1| 2| 5|| 2| 1| 2|| 2| 1| 2||
3| 1| 1 | +---------+----------+----------+
Cuando se ordena por varias columnas, por ejemplo 3, el procedimiento es básicamente el que sigue : Se ordena por la
primera columna. Si hay valores repetidos en la primera columna, para cada grupo de valores repetidos se ordenan las
filas por el valor de la 2ª columna. Si hay valores repetidos de las dos primeras columnas en conjunto, se ordenan las
filas correspondientes por la 3ª columna. Ejemplo: Supongamos una tabla con las siguientes columnas y valores:
+-----+-----------------------+------------+----------+ | a | b |c |d | +-----+-----------------------+------------+--
--------+ | 125 | Diana Pérez | 1/1/2004 | 12313 | | 486 | Alejandro Bentancourt | 30/12/2005 | 45646 | | 222 |
Jorge Rodríguez | 2/5/2004 | 78987 | | 125 | Diana Pérez | 3/8/2004 | 654654 | | 222 | Adriana Salgado
| 1/3/2002 | 12312 | +-----+-----------------------+------------+----------+
Si ordenamos esta tabla por las columnas a, b y c, obtenemos
+-----+-----------------------+------------+----------+ | a | b |c |d | +-----+-----------------------+------------+-----
-----+ | 125 | Diana Pérez | 1/1/2004 | 12313 | | 125 | Diana Pérez | 3/8/2004 | 654654 | | 222 | Adriana
Salgado | 1/3/2002 | 12312 | | 222 | Jorge Rodríguez | 2/5/2004 | 78987 | | 486 | Alejandro Bentancourt |
30/12/2005 | 45646 | +----+-------------+-----------------------+----------+
Por último, se puede ordenar por una cantidad calculada a partir de una o varias columnas.
mysql> SELECT articulo, importe, cantidad FROM ventas -> ORDER BY articulo, importe/cantidad; +----------+---------
+----------+ | articulo | importe | cantidad | +----------+---------+----------+ | 1 | 178.50 | 1|| 1 | 178.50 | 1||
2 | 195.00 | 1|| 2 | 200.00 | 1|| 3 | 220.00 | 1|| 5 | 5.50 | 1|| 5 | 11.00 |
2|| 5 | 5.50 | 1|| 7 | 16.00 | 2 | +----------+---------+----------+

La cláusula LIMIT
La preparación de un query complicado implica normalmente un proceso de prueba y error. Aunque no se cometan
errores, siempre se empieza escribiendo queries que sólo realizan una parte de lo que se desea alcanzar. Luego, se van
mejorando gradualmente hasta llegar al objetivo buscado.

Cuando se trabaja con tablas auténticas con muchos miles de filas, puede ser demasiado engorroso ir obteniendo
repetidas salidas con cientos o miles de filas. Es obvio que no se pueden observar en la pantalla del cliente mysql. Más
adelante, veremos cómo usar Microsoft Excel para observar las salidas de los queries. Por otra parte, en su instalación
puede haber otros clientes que operen con MySQL.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

De todas maneras, interesa una cláusula sencilla que limite el número de filas que produce el SELECT. Esa es la
función de LIMIT. Si, por ejemplo, escribimos
mysql> SELECT articulo, cliente FROM ventas LIMIT 3; +----------+---------+ | articulo | cliente | +----------+---------+ | 1|
1|| 2| 2|| 1| 3 | +----------+---------+
entonces sólo vemos 3 filas en la salida, a pesar que hay varias más en Ventas.

El orden de las cláusulas.


Las cláusulas mencionadas, SELECT...FROM.. , WHERE, ORDER BY, y LIMIT deben escribirse, si aparecen, en ese
orden. SELECT siempre aparece y va en primer lugar. Las otras 3 son optativas.

Cómo ingresar queries.


Hasta ahora hemos venido escribiendo a continuación del prompt mysql> del cliente mysql.

Este procedimiento es inconveniente apenas se empiezan a complicar los queries. Un procedimiento sencillo para
Windows, es el siguiente:

- Inicie el programa Bloc de Notas. Suele estar en Inicio, Programas, Accesorios.

- Escriba en él su query.

- Guárdelo en nuestro directorio de trabajo : C:\MySQL\bin\p. con un nombre sencillo que le parezca apropiado como
prueba.txt. Nota : El Bloc de Notas agrega automáticamente .txt al final del nombre de archivo así que sólo escriba
prueba, sin punto al final. ¡Si escribe prueba. se guardará como prueba..txt, con 2 puntos!

- Vaya al cliente mysql y escriba

mysql> SOURCE p/prueba.txt


o, si lo prefiere,
mysql> \. p/prueba.txt

- Si el query no dio el resultado esperado, ahora no es preciso escribir todo de nuevo. Simplemente corríjalo en el Bloc
de Notas. y vuelva a guardarlo. Repita los pasos d) y e) hasta obtener el resultado buscado. Si lo desea, ahora puede
archivar el query con un nombre más descriptivo, usando la opción Guardar como del menú Archivo del Bloc de Notas.

Nota sobre la arquitectura Cliente-Servidor


A esta altura, más de un lector se hará la pregunta de para qué existe la separación entre el servidor MySQL y el
cliente mysql. ¿ No podría ser todo un solo programa? La respuesta es que normalmente se va a trabajar en red con un
servidor y muchos clientes.

Los clientes son programas relativamente sencillos que se pueden programar para que estén adaptados a las
necesidades del usuario. En cambio, los servidores son programas complejos que realmente no se pueden adaptar a las
necesidades de un usuario individual (aunque son configurables, por ejemplo, pueden emitir mensajes en un idioma
seleccionado por el administrador de la base de datos).

Problemas resueltos

- Obtener todos los datos de la tabla Empleados.


Solución :
El problema es obtener todos las columnas de todas las filas de la tabla Empleados.
Query :
SELECT * FROM Empleados;

- Obtener los nombres y las fechas de ingreso de los empleados.


Solución :
Formalmente, queremos obtener las columnas Nombre, Fecha_ingreso de todas las filas de la tabla Empleados. El
query es:
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

SELECT Nombre, Fecha_ingreso FROM Empleados;

- Obtener los datos de los empleados que ganan más de $ 10500,50.


Solución:
Queremos obtener todas las columnas de las filas de Empleados para las cuales Salario es mayor que 10500,50. El
query es:

SELECT * FROM Empleados WHERE Salario > 10500.50;


Obsérvese el uso del punto decimal. Las comas no se pueden utilizar ni en lugar del punto decimal ni para separar
los miles (en un query).

- Queremos obtener los datos del funcionario Carlos Zaltzman.


Solución:
Se trata de obtener una fila de Empleados, aquella en la cual el nombre del funcionario es Carlos Zaltzman. El query es:

SELECT * FROM Empleados WHERE Nombre = 'Carlos Zaltzman';


Este método no es muy práctico. En primer lugar el nombre debe ser escrito en el query casi exactamente como
está en la tabla. Con todo, los diseñadores de MySQL han tenido el sentido común de incluir en un select como este
a filas (si existiesen) con Nombre &lsquo;carlos zaltzman&rsquo; o &lsquo;Carlos Zaltzman &lsquo;. Es decir: no se
tienen en cuenta mayúsculas y minúsculas, ni blancos al final.

Sin embargo, sigue siendo muy poco práctico. Además, si hay dos empleados con el mismo nombre, no hay manera
de distinguirlos, si no se usa otra columna. Por eso todas las empresas tienen números de funcionario.

- ¿Qué empleados ingresaron el 3 de enero del 2000?.


Solución:
Se trata de obtener filas de Empleados, aquellas en las cuales la fecha de ingreso sea '2000-1-3'. El formato apropiado
para la fecha es Año-Mes-Día. El query es :

SELECT * FROM Empleados WHERE Fecha_ingreso = '2000-1-3';

- ¿Qué empleados ingresaron en fecha posterior al 1º de enero del 2000?


Solución:
Queremos obtener las filas de Empleados con fecha de ingreso mayor que '2000-1-1'. El query es :

SELECT * FROM Empleados WHERE Fecha_ingreso>'2000-1-1';

- ¿Qué empleados ingresaron el 5 de enero del 2000 o en una fecha posterior?


Solución:
La fecha de ingreso debe ser mayor o igual a '2001-1-5'. El query es :

SELECT * FROM Empleados WHERE Fecha_ingreso>='2000-1-5';

- Sacar una lista de los nombres de los clientes de los cuales no se tiene dirección.
Solución:
Se trata de obtener la columna Nombre de las filas de la tabla Clientes cuya dirección es NULL. El query es :

SELECT Nombre FROM Clientes WHERE Direccion IS NULL;

- Sacar una lista de los nombres y direcciones de los clientes de los cuales sí se tiene la dirección.
Solución:
Se trata de obtener la columnas Nombre, Direccion de las filas de la tabla Clientes que tienen direcciones que no sean
NULL. El query es:

SELECT Nombre,Direccion FROM Clientes WHERE Direccion IS NOT NULL;


http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

- Obtener una lista de los diferentes salarios que se pagan en la empresa.


Solución:

SELECT DISTINCT Salario FROM Empleados;

- Sacar una lista ordenada alfabéticamente de los nombre y direcciones de los clientes, ordenados por nombre.
Solución:

SELECT Nombre,Direccion FROM Clientes ORDER BY Nombre;

- Sacar una lista de todos los datos de los empleados ordenados por nombre.
Solución:

SELECT * FROM Empleados ORDER BY Nombre;

- Sacar una lista de los datos de los empleados ordenados por salario en forma descedente. Los salarios deben ser
formateados con comas cada 3 dígitos y dos decimales después del punto y alineados a la derecha , por ejemplo,
1,200,340.50.
Solución:

SELECT Id, Nombre, Fecha_ingreso, LPAD( FORMAT(Salario,2) , 12 , ' ' ) AS


Salario FROM Empleados ORDER BY Salario DESC;

- Igual al anterior pero se quiere que los números salgan formateados con puntos cada 3 dígitos y coma decimal, en
vez de punto. Por ejemplo, 1.200.340,50 .
Solución:

SELECT Id, Nombre, Fecha_ingreso, REPLACE( REPLACE(


REPLACE( LPAD(FORMAT(Salario,2),12,' '), '.','!'), ',','.'),
'!',',') AS Salario FROM Empleados ORDER BY Salario DESC;

Si bien es un procedimiento complicado, para usarlo en otro caso sólo hay que copiar la parte que comienza con
REPLACE y termina en el paréntesis antes de AS Salario y hacer los siguientes cambios:

- Cambiar la columna Salario por la que se vaya a usar.

- Eventualmente cambiar el número de decimales después de la coma, que figura dentro de la función FORMAT, de 2
al valor que se desee.

- Si es conveniente, variar el ancho de la columna. Este ancho aparece dentro de la función LPAD. En este ejemplo vale
12. El ancho debe ser suficiente para poder escribir todos los valores que aparezcan en la columna, con el número de
decimales que se haya solicitado.

Manejo de fechas
SELECT como calculadora
Se puede usar la cláusula SELECT para hacer cálculos aritméticos.

Ejemplos:
SELECT 1+1; SELECT 4.5*(3.86+2.34)
Se debe usar punto decimal y no coma.

Se puede usar la función POW ( por power, potencia) para hacer cálculos relativos a intereses.

POW(a,b) calcula a elevado a la potencia b. Por ejemplo, POW(10,3) produce el valor 1000.
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

También se pueden hacer cálculos trigonométricos, etc, pero, en general, estos cálculos no relacionados con bases
de datos se hacen mejor con una calculadora.

Cálculos con fechas


Donde sí resulta realmente interesante el poder de cálculo de MySQL, es con los cálculos relativos a fechas. Para esos
cálculos, necesitaremos unas cuantas funciones. Para los ejemplos, supondremos que hoy es 1/1/2005.

- CURDATE(). Esta función da la fecha del día (¡si el sistema tiene la fecha correcta!). Ejemplo:
SELECT CURDATE();
Obtenemos 2005-01-01, en el formato de fecha &lsquo;Año-Mes-Día&rsquo; propio de MySQL.

- DAYNAME(). Dada una fecha, esta función da el nombe ( en inglés) del día de la semana correspondiente. Ejemplo:
SELECT DAYNAME(CURDATE());
Obtenemos Saturday, es decir, Sábado.

- DAYOFWEEK(). Es complementaria de la anterior. En vez de darnos el nombre del día de la semana nos da un código
numérico de 1 a 7. El código 1 representa el Domingo, el 2 el Lunes, y así hasta el 7 que representa el Sábado. Ejemplo:
SELECT DAYOFWEEK(CURDATE());
Obtenemos un 7,que indica el Sábado.

- DATE_FORMAT(). Nos permite presentar las fechas en otros formatos. Los formatos que usaremos son '%d/%m/%y'
y '%d/%m/%Y'. Ejemplo:
SELECT DATE_FORMAT(CURDATE(),&rsquo;%d/%m/%Y');
Produce 01/01/2005.

- DATE_ADD(). Esta función nos permite agregar a una fecha cierto número de días ( o meses y años) Ejemplo: ¿Cuál
es la fecha de dentro de 15 días?
SELECT DATE_ADD(CURDATE(), INTERVAL 15 DAY);
o mejor :
SELECT DATE_FORMAT(DATE_ADD(CURDATE(),INTERVAL 15 DAY) ,&rsquo;%d/%m/%Y');
Produce 16/01/2005.

- DATE_SUB(). Esta función le quita cierto número de días (o meses y años) a una fecha. Ejemplo: ¿Cuál es la fecha
de hace 15 días?
SELECT DATE_FORMAT(DATE_SUB(CURDATE(),INTERVAL 15 DAY),&rsquo;%d/%m/%Y');
Produce 17/12/2004.

- DATEDIFF(). Esta función obtiene la diferencia, en días, entre dos fechas. Ejemplo :
SELECT DATEDIFF(&lsquo;2005-4-1&rsquo;,&rsquo;2004-5-30&rsquo;);
Este query produce 306, lo que significa que del 30/5/2004 al 1/4/2005 van 306 días.

- YEAR(), MONTH() ,DAY() extraen de una fecha el año, el mes y día correspondientes. Ejemplo:
SELECT MONTH(&lsquo;2005-4-1&rsquo;); produce 4, el número del mes.

Problemas resueltos

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

- ¿A qué fecha estamos?


Solución:
SELECT CURDATE();
La instrucción SELECT se puede usar para hacer diversas operaciones que no tienen relación con una base de datos.
En este caso, nos da la fecha. Esta fecha sale en el formato año-mes-día que puede resultar difícil de leer para muchas
personas. Por eso, es mejor
SELECT DATE_FORMAT(CURDATE(),'%d / %m / %y');
con lo que se obtiene el formato día/mes/año usual. El uso de blancos antes y después de los signos / es opcional.

En general la función DATE_FORMAT( .........., '%d / %m / %y') nos sirve para presentar cualquier fecha en un formato
legible.

- ¿Qué día de la semana es hoy?


Solución:
Si nos conformamos con un resultado en inglés alcanza con
SELECT DAYNAME(CURDATE());
Para obtener el día de la semana en español hay que escribir un poco más :
SELECT CASE DAYOFWEEK(CURDATE()) WHEN 1 THEN 'Domingo' WHEN 2
THEN 'Lunes' WHEN 3 THEN 'Martes' WHEN 4 THEN CONCAT('Mi',CHAR(130),'rcoles')
WHEN 5 THEN 'Jueves' WHEN 6 THEN 'Viernes' WHEN 7 THEN
CONCAT('S',CHAR(160),'bado') END AS Dia_de_la_Semana;
Este mismo método puede aplicarse a cualquier fecha sustituyendo el CURDATE() de la primera línea por la fecha
dada.

- Obtener una lista de los empleados que ingresaron después del 15/12/1999, con sus nombres y fechas de ingreso en
el formato usual día/mes/año (el año con 4 cifras).
Solución:
SELECT Nombre,DATE_FORMAT(Fecha_ingreso,'%d/%m/%Y') AS Fecha_de_Ingreso
FROM Empleados WHERE Fecha_ingreso > '1999-12-15';
La %Y en el formato de la fecha produce el año con 4 cifras.

- ¿Qué ventas se han realizado en los últimos 25 días?


Solución:
Incluimos el día de hoy entre los 25 días mencionados.
SELECT * FROM Ventas WHERE Fecha > DATE_SUB(CURDATE(), INTERVAL 25 DAY);

- ¿ Qué ventas se han realizado en el corriente mes?


Solución:
SELECT * FROM Ventas WHERE Fecha > DATE_SUB(CURDATE(), INTERVAL
DAYOFMONTH(CURDATE()) DAY);
¿Cómo funciona este query?

Primero se evalúa CURDATE() dando la fecha del día. DAYOFMONTH separa de esa fecha el día del mes.
Supongamos que se trata de un día 3. Entonces DATE_SUB le resta a su primer parámetro CURDATE(), el número de
día del mes. Pero 3 días antes del 3 de mes está el último día del mes anterior. Una fecha mayor que el último día del
mes anterior es lo mismo que una fecha del mes actual.

- ¿Qué conformes a pagar se vencen durante los próximos 18 días?


Solución:
SELECT * FROM CONFORMES WHERE Vencimiento<=DATE_ADD(CURDATE(),INTERVAL 18 DAY);

- Realizar una tabla con los datos de los conformes, pero agregando una columnas donde se indica cuántos días faltan
para el vencimiento de cada uno.
Solución:
SELECT *, DATEDIFF(Vencimiento,CURDATE()) AS Dias_para_Vencimiento FROM Conformes;
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

- Obtener una lista de los conformes con sus fechas de vencimiento en la forma , por ejemplo, 3 de Febrero de 2004 ,
ordenados por fecha de vencimiento de manera que el conforme que se vence primero aparezca primero en la lista.
Solución:
En inglés las fechas se formatean con facilidad:
SELECT Acreedor, DATE_FORMAT(Vencimiento,'%M %D, %Y') AS Vencimiento, Importe
FROM Conformes ORDER BY Vencimiento;
Para obtener un resultando semejante en español hay que escribir:
SELECT Acreedor, CONCAT( DAYOFMONTH(Vencimiento), ' de ',
CASE MONTH(Vencimiento) WHEN 1 THEN 'Enero' WHEN 2 THEN
'Febero' WHEN 3 THEN 'Marzo' WHEN 4 THEN 'Abril' WHEN 5
THEN 'Mayo' WHEN 6 THEN 'Junio' WHEN 7 THEN 'Julio'
WHEN 8 THEN 'Agosto' WHEN 9 THEN 'Setiembre' WHEN 10 THEN 'Octubre'
WHEN 11 THEN 'Noviembre' WHEN 12 THEN 'Diciembre' END,
' de ', YEAR(Vencimiento)) AS Vencimiento, Importe FROM Conformes;

- Obtener una lista de los empleados con el número de años que llevan en la empresa al día de hoy. Se cuentan
únicamente años enteros. Por ejemplo, si un empleado lleva 5 años y 10 meses en la empresa, contamos
únicamente 5 años.
Solución:
SELECT *, YEAR(CURDATE()) - YEAR(Fecha_ingreso) - (RIGHT(CURDATE(),5) <
RIGHT(Fecha_ingreso,5)) AS Antiguedad FROM Empleados;
Veamos cómo funciona este query, que es bastante complejo. En primer lugar, aparece un valor booleano
RIGHT(CURDATE(),5) < RIGHT(Fecha_ingreso,5). Para entender este valor, en primer lugar debemos darnos cuenta
que RIGHT(CURDATE(),5) representa los 5 caracteres más a la derecha de CURDATE(). Es decir, los dos dígitos del
mes de hoy, un guión, y los dos dígitos del día de hoy.

El signo de < que separa los dos RIGHT representa en realidad una pregunta : ¿ el primero da un resultado
alfabéticamente anterior al segundo ? Esto es equivalente a preguntar si la fecha de hoy es anterior al día en que se
cumplen años de la fecha de ingreso. Ahora bien, el hecho que una condición sea verdadera se representa en el
computador por un valor 1 mientras que si la condición es falsa se guarda un valor 0.

Entonces, si la desigualdad es verdadera la expresión (RIGHT(CURDATE(),5) < RIGHT(Fecha_ingreso,5)) vale 1. En


caso contrario, vale 0.

Veamos un ejemplo completo. Si un empleado hubiese ingresado el 20 de diciembre del año y hoy es 10 de octubre,
entonces todavía no cumplió un año. Obtenemos un resultado correcto porque YEAR(CURDATE()) -
YEAR(Fecha_ingreso) vale 1 y (RIGHT(CURDATE(),5) < RIGHT(Fecha_ingreso,5)) también vale 1. La diferencia, cero,
indica que el empleado todavía no tiene un año en la empresa.

Cuando llegue el 20 de diciembre, la expresión (RIGHT(CURDATE(),5) < RIGHT(Fecha_ingreso,5)) pasa a valer 0 y la


diferencia YEAR(CURDATE()) - YEAR(Fecha_ingreso) - (RIGHT(CURDATE(),5) < RIGHT(Fecha_ingreso,5)) pasa a
valer 1. Es decir, ahora el empleado ha cumplido un año en la empresa.

Este truco es útil porque muchas reglamentaciones sobre licencias y primas dependen de los años enteros que tenga
el empleado.

Funciones de agregados. (Aggregate functions)


A menudo queremos realizar operaciones sobre un conjunto de filas de una tabla. Por ejemplo, queremos sumar los
contenidos de una columna Importe en toda la tabla, o sólo en las filas que cumplen cierta condición. Para eso existen
ciertas funciones llamadas funciones de agregados (Aggregate functions).

Veremos algunas de estas funciones:

- SUM(). Esta función totaliza una columna, dentro de las filas que cumplen una condición, o de todas las filas si no es
especifica ninguna condición. En lo que sigue abreviaremos esta expresión y diremos simplemente &lsquo;de las filas
especificadas&rsquo;. Ejemplos: Sumar todos los importes de Ventas.
mysql> SELECT SUM(importe) FROM ventas; +--------------+ | SUM(importe) | +--------------+ | 1010.00 | +--------------
+
Sumar todos los importes de Ventas, con fecha del año 2003.
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

mysql> SELECT SUM(importe) FROM ventas WHERE YEAR(fecha)=2003; +--------------+ | SUM(importe) | +--------------
+| NULL | +--------------+

- COUNT(*). Cuenta todas las filas especificadas. Por ejemplo, el siguiente query produce el número de filas de la tabla
lineas_factura.
mysql> SELECT COUNT(*) FROM lineas_factura; +----------+ | COUNT(*) | +----------+ | 5 | +----------+

- COUNT(Nombre_de_columna). Cuenta cuántos valores no NULL hay de la columna especificada dentro de las filas
especificadas. Por ejemplo, el siguiente query produce el número de direcciones de clientes que tenemos registradas.
mysql> SELECT COUNT(direccion) FROM clientes; +------------------+ | COUNT(direccion) | +------------------+ |
2 | +------------------+

- COUNT ( DISTINCT Nombre_de_columna). Cuenta cuántos valores no NULL diferentes hay de la columna
especificada, en las filas especificadas. El siguiente ejemplo produce el número de clientes distintos a los cuales se les
han registrado ventas.
mysql> SELECT COUNT(DISTINCT(cliente)) FROM ventas; +--------------------------+ | COUNT(DISTINCT(cliente)) | +---
-----------------------+ | 3 | +--------------------------+

- MAX(). Produce el máximo valor de una columna dentro de las filas especificadas.

- MIN(). Produce el mínimo valor de una columna en las filas especificadas.

- AVG(). Produce el promedio de los valores de una columna numérica, contando sólo las filas especificadas.

Introducción a las subqueries


Un subquery es una instrucción SELECT dentro de otra instrucción. Los subqueries que vamos a estudiar en esta sección
son llamado subqueries escalares. Producen una sola cantidad que como de costumbre puede ser numérica, una
cadena de caracteres o una fecha.

Un subquery siempre debe estar rodeado de paréntesis. Usaremos subqueries para crear condiciones en cláusulas
WHERE.

Problemas resueltos

- Obtener la suma de los salarios pagos en la Empresa.


Solución:
Debemos obtener la suma de la columna Salario en la tabla Empleados.
SELECT SUM(Salario) FROM Empleados;

- Obtener la suma de los salarios mayores a 11000.


Solución:
Debemos obtener la suma de la columna Salario de aquellas filas de Empleados que tienen Salario mayor a 11000.
SELECT SUM(Salario) FROM Empleados WHERE Salario > 11000;

- Contar cuántos empleados tiene la empresa.


Solución:
Debemos obtener el número de filas en la tabla Empleados.
SELECT COUNT(*) FROM Empleados;

- Contar cuánto empleados tienen salario menor de 11000.


Solución:
Debemos obtener el número de filas en la tabla Empleados con Salario <11000.
SELECT COUNT(*) FROM Empleados WHERE Salario < 11000;

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

- Contar cuántas direcciones de clientes se tienen.


Solución:
Debemos obtener el número de filas de Clientes cuya columna Direccion no es NULL.
SELECT COUNT(Direccion) FROM Clientes;
Observar que como se especificó COUNT(Direccion) las direcciones NULL no se cuentan. En cambio SELECT
COUNT(*) FROM Clientes cuenta todas las filas, independientemente que tengan o no dirección (o algúna otra columna)
NULL.

- ¿Cuál es el salario promedio de la empresa?


Solución:

SELECT AVG(Salario) FROM Empleados;

- ¿Cuál es el salario máximo pago por la empresa?


Solución:

SELECT MAX(Salario) FROM Empleados;

- ¿Y el salario mínimo?
Solución:

SELECT MIN(Salario) FROM Empleados;

- ¿Cuál son los empleados más antiguos de la empresa?


Solución:
Vamos a seleccionar todas las filas de la tabla Empleados con Fecha de Ingreso igual a la fecha de ingreso mínima.
SELECT * FROM Empleados WHERE Fecha_ingreso = (SELECT MIN(Fecha_ingreso)
FROM Empleados);

- Hallar los nombres de los empleados con salario máximo en la empresa.


Solución:

SELECT Nombre FROM Empleados WHERE Salario = (SELECT MAX(Salario) FROM


Empleados);

- ¿Cuántos salarios distintos se pagan en la empresa?


Solución:

SELECT COUNT(DISTINCT Salario) FROM Empleados;

Agrupando datos
La cláusula GROUP BY.

A menudo interesa agrupar las filas según algún criterio, que suele ser el valor de una columna, o varias. Una
cláusula SELECT con un GROUP BY produce una sola fila por cada grupo. Los valores de las columnas especificadas
en el SELECT deberían ser iguales dentro de cada grupo. De lo contrario los resultados son imprevisibles.

También aparecen usualmente funciones de agregado que ahora se calculan sobre cada grupo. Los resultados, si no
especifica otra cosa con un ORDER BY, salen ordenados por las columnas del GROUP BY.
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

Ejemplo: ¿Cuántas líneas tiene cada una de las facturas? Veamos la tabla Lineas_factura:

+----+---------+-------+ | id | factura | venta | +----+---------+-------+ | 1 | 1| 1|| 2| 1| 6|| 3| 1| 7|| 4|


2| 2|| 5| 3 | 3 | +----+---------+-------+

Veamos el resultado de efectuar el siguiente query.


mysql> SELECT factura, COUNT(*) FROM lineas_factura GROUP BY factura; +---------+----------+ | factura | COUNT(*) |
+---------+----------+ | 1| 3|| 2| 1|| 3| 1 | +---------+----------+
Es decir, que tenemos una factura 1 con 3 líneas y otras, 2 y 3, con una línea cada una.

La cláusula HAVING.
Después de un GROUP BY, todavía se pueden volver a seleccionar filas con una cláusula HAVING. Por ejemplo,
podemos estar interesados, hipotéticamente, en las facturas con más de una línea. Entonces deberíamos usar
SELECT Factura, COUNT(*) FROM Lineas_Factura GROUP BY Factura HAVING COUNT(*) > 1;

Si no nos interesa ver el número de líneas podemos usar


SELECT Factura FROM Lineas_Factura GROUP BY Factura HAVING COUNT(*) > 1;

Otra variante más legible


mysql> SELECT factura, COUNT(*) AS cantidad FROM lineas_factura -> GROUP BY factura HAVING cantidad > 1;

El resultado es:
+---------+----------+ | factura | cantidad | +---------+----------+ | 1| 3 | +---------+----------+
El orden de las cláusulas vistas hasta ahora es SELECT.....FROM...., WHERE, GROUP BY, HAVING, ORDER BY,
LIMIT.

Hay dos momentos en que se seleccionan filas, una con el WHERE antes de la agrupación y otro con el HAVING,
después de la misma.

Problemas resueltos

- Cuánto totalizan las ventas de cada sucursal?


Solución:

En la tabla Ventas tenemos una columna Sucursal. Esa columna contiene un código numérico que por ahora utilizaremos
tal como está. ( Más adelante, le haremos corresponder a cada código numérico su descripción del tipo 1=Centro,
2=Unión, etc. Estos son barrios de la bella ciudad de Montevideo, donde es nacido el autor). Un valor NULL de Sucursal
puede representar una venta no asociada a una región determinada, por ejemplo una exportación inusual o una venta al
Estado. Queremos para cada Sucursal totalizar los Importes correspondientes.
SELECT Sucursal, SUM(Importe) FROM Ventas GROUP BY Sucursal;
Una presentación algo mejor se logra con:
SELECT Sucursal, SUM(Importe) as Ventas_Totales FROM Ventas GROUP BY Sucursal;

- ¿Cuántas ventas se efectuaron en cada región?


Solución:
SELECT Sucursal, COUNT(*) as Numero_Ventas FROM Ventas GROUP BY Sucursal;

- ¿Cuántas ventas se efectuaron en cada región, por cada vendedor? Sólo se van a incluir en este informe las ventas con
datos completos. No admitimos Sucursal o Vendedor NULL.
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

Solución:
SELECT Sucursal, Vendedor, COUNT(*) AS Numero_Ventas FROM Ventas WHERE Sucursal IS
NOT NULL AND Vendedor IS NOT NULL GROUP BY Sucursal, Vendedor;

- ¿Cuál fue el importe promedio de las ventas en cada región?


Solución:
SELECT Sucursal, AVG(Importe) AS Venta_Promedio FROM Ventas GROUP BY Sucursal;
Este query genera una salida un tanto confusa debido a que los promedios tienen demasiados decimales. Por
ejemplo, uno de los promedios aparece como 137.000000 . Para evitar esto, es recomendable utilizar
SELECT Sucursal, ROUND(AVG(Importe),2) AS Venta_Promedio FROM Ventas GROUP BY
Sucursal;
La expresión ROUND(AVG(Importe),2) indica a MySQL que promedie los importes. redondee el resultado a 2 dígitos
después de la coma. Si no queremos decimales podemos usar
SELECT Sucursal, ROUND(AVG(Importe)) AS Venta_Promedio FROM Ventas GROUP BY
Sucursal;

- Ahora queremos totalizar los importes de las ventas de cada vendedor en cada región.
Solución:
Le vamos a pedir a MySQL que sume los importes agrupando por vendedor y región.
SELECT Vendedor, Sucursal, SUM(Importe) AS Total FROM Ventas GROUP BY Vendedor,
Sucursal;

- Queremos totalizar los importes de las ventas de cada vendedor y además el total general de las ventas.
Solución:

SELECT Vendedor, SUM(Importe) AS Total FROM Ventas GROUP BY Vendedor WITH ROLLUP;
El total está en la última fila. Aparecen dos filas con Vendedor NULL. La primera corresponde a las ventas para las
que no se tiene un vendedor en la tabla. La última contiene el total general, como es fácil verificar. Este total general
aparece debido a que se agregó WITH ROLLUP al GROUP BY.

- Queremos totalizar los importes de las ventas por vendedor y región pero además obtener subtotales por vendedor y
un total general.
Solución:

SELECT Vendedor, Sucursal,SUM(Importe) AS Total FROM Ventas GROUP BY Vendedor,


Sucursal WITH ROLLUP;
Las presencia de filas con Vendedor y/o Sucursal NULL complica la lectura. Es preferible usar este método con
agrupación por columnas que no presenten valores NULL.

- Queremos el promedio de las ventas de cada vendedor.


Solución :
SELECT ROUND(AVG(Total)) FROM ( SELECT Vendedor, SUM(Importe) AS Total FROM
Ventas GROUP BY Vendedor HAVING Vendedor IS NOT NULL) AS Totales;
Hay varios puntos interesantes y novedosos en este query. Estamos usando un subquery para crear la tabla
temporaria Totales. Esa tabla contiene el nombre del Vendedor y el Total de sus ventas. Se agrega una cláusula
HAVING para no incluir el Vendedor NULL (es decir las ventas en las que no intervino un vendedor directamente).

Después del subquery es imprescindible agregar "AS Totales" para darle un nombre ("Totales") a la tabla temporaria .
Es decir, si el subquery se usa para generar una tabla temporaria de la cual se realiza un SELECT...FROM, es decir, de
la cual se seleccionan filas, entonces es preciso asignarle un nombre a la tabla temporaria. El nombre se le asigna
usando "AS".

De nuevo usamos ROUND para evitar las cifras después de la coma.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

Vinculaciones entre tablas


Supongamos que hiciéramos todas las combinaciones entre las filas de 2 o más tablas. Obtendríamos una nueva tabla
con un número de filas igual al producto de los números de filas de las tablas consideradas. Esta tabla es el JOIN (se
puede traducir como zona de unión, el verbo to join significa unir) de las tablas dadas.

Por ejemplo, supongamos que hacemos esta operación con las tablas T1 y T2
T1 +------+------+ | a | b | +------+------+ | 1 | 4 | | 2 | 9 | | 3 | 7 | +------+------+ T2 +------+------+ | c | d | +---
---+------+ | AB | 4 | | CD | 10 | | EF | 9 | +------+------+
Entonces el JOIN de T1 y T2 es :
+------+------+------+------+ | a | b | c | d | +------+------+------+------+ | 1 | 4 | AB | 4 | | 2 | 9 | AB | 4 | | 3
| 7 | AB | 4 | | 1 | 4 | CD | 10 | | 2 | 9 | CD | 10 | | 3 | 7 | CD | 10 | | 1 | 4 | EF | 9 | | 2 | 9 |
EF | 9 | | 3 | 7 | EF | 9 | +------+------+------+------+

La cláusula ON
Generalmente, no nos interesa obtener todas las combinaciones de filas, sino únicamente aquellas que cumplen cierta
condición. Esa condición se especifica en la cláusula ON. Por ejemplo, si efectuásemos el query
SELECT * FROM T1 JOIN T2 ON T1.b=T2.d;
obtendríamos únicamente las filas del JOIN donde b y d coinciden, es decir:
+------+------+------+------+ | a | b | c | d | +------+------+------+------+ | 1 | 4 | AB | 4 | | 2 | 9 | EF | 9 | +-----
-+------+------+------+
Supongamos ahora, que queremos hacer un listado donde figure cada fila de T1 combinada con cada fila de T2 que
tenga T1.b = T2.d, y además, la fila de T1 seguida de una fila de T2 llena de NULL si no hay ninguna fila de T2 que
verifique la condición del ON con la fila de T1 dada. Esto es lo que se llama un LEFT JOIN. El query
SELECT * FROM T1 LEFT JOIN T2 ON T1.b=T2.d;
produce la tabla
+------+------+------+------+ | a | b | c | d | +------+------+------+------+ | 1 | 4 | AB | 4 | | 2 | 9 | EF | 9 | | 3
| 7 | NULL | NULL | +------+------+------+------+
La última fila aparece debido a la inexistencia de valores de d iguales a b=7 en la tabla T2.

Si, al revés, queremos que toda fila de T2 aparezca precedida de las filas de T1 que le corresponden, si las hay, y si no,
una fila llena de NULL, entonces tenemos que hacer un RIGHT JOIN. El query
SELECT * FROM T1 RIGHT JOIN T2 ON T1.b=T2.d;
produce
+------+------+------+------+ | a | b | c | d | +------+------+------+------+ | 1 | 4 | AB | 4 | | NULL | NULL | CD | 10
| | 2 | 9 | EF | 9 | +------+------+------+------+
Para prepararnos para los problemas resueltos, veamos las siguientes tablas:

Clientes
+----+-------------+---------------------+----------+ | id | nombre | direccion | vendedor | +----+-------------+--------------------
-+----------+ | 1 | Matt Design | NULL | 1 | | 2 | Diana Pérez | Brito del Pino 1120 | NULL | | 3 | John
Smith | Zum Felde 2024 | 1 | +----+-------------+---------------------+----------+
Empleados
+----+-----------------+---------------+---------+ | id | nombre | fecha_ingreso | salario | +----+-----------------+---------------+----
-----+ | 1 | Carlos Zaltzman | 1999-12-10 | 10000 | | 2 | Juan Fernández | 2000-01-03 | 12000 | +----+-----------------
+---------------+---------+
Algunos clientes son atendidos por un vendedor de la empresa. El vendedor que atiende a un clientes es identificado en
la columna Vendedor por su código. El 1 que aparece en la primera fila de Clientes significa que Matt Design es atendido
por el empleado Carlos Zaltzman, que tiene código 1. Sin entrar en detalles, MySQL "sabe" que la columna Vendedor de
Clientes se refiere a la columna Codigo de Empleados.

El NULL de la segunda fila de Clientes significa que no es atendido por ningún vendedor. La columna Vendedor de
Clientes es lo que se llama una clave extranjera ("foreign key"). La columna Id de Empleados es una clave primaria
(identifica completamente a un empleado). La clave extranjera Vendedor de Clientes es una referencia a la clave
primaria Id de Empleado.

También tenemos las primeras filas y columnas de la tabla Ventas.


+----+---------+----------+---------+ | id | cliente | vendedor | importe | +----+---------+----------+---------+ | 1 | 1| 1|
178.50 | | 2 | 2| 1 | 195.00 | | 3 | 3| 1 | 178.50 | | 4 | 1| 1 | 16.00 | +----+---------+----------+------
---+
La primera columna Id identifica la venta (es una clave primaria). La segunda columna Cliente es una clave extranjera
que se refiere a la clave primaria Id de Clientes. La columna Vendedor es una clave extranjera que se refiere a la clave
primaria Id de Empleados.
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

Por ejemplo, la primera fila significa que la venta identificada por el número 1 fue realizada al cliente Matt Design por el
vendedor Carlos Zaltzman, por un importe de 178.50.
Problemas resueltos

- Se busca hacer una tabla con los nombres de los clientes que son atendidos por un vendedor y el nombre del
correspondiente vendedor.
Solución:
Formamos una tabla con el Nombre de los Clientes y de los Empleados que tengan el Vendedor del Cliente igual al
Código del Empleado.
SELECT Clientes.Nombre, Empleados.Nombre FROM Clientes JOIN Empleados ON
Clientes.Vendedor = Empleados.Id;

- Ahora queremos que aparezcan en la tabla también los clientes que no son atendidos por ningún vendedor. El
nombre del vendedor aparecerá como NULL.
Solución:

SELECT Clientes.Nombre, Empleados.Nombre FROM Clientes LEFT JOIN Empleados ON


Clientes.Vendedor = Empleados.Id;
También :
SELECT Clientes.Nombre,Empleados.Nombre FROM Empleados RIGHT JOIN Clientes ON
Clientes.Vendedor = Empleados.Id;

- En este caso queremos hacer una tabla con los nombres de los empleados y al lado de ellos los nombres de los
clientes. Si un empleado atiende varios clientes aparecerá en varias filas. Si no atiende ninguno aparecerá una sola
vez con un NULL en la columna de cliente.
Solución:

SELECT Empleados.Nombre, Clientes.Nombre FROM Empleados LEFT JOIN Clientes ON


Clientes.Vendedor = Empleados.Id;

- Hacer una tabla en la cual figuren para cada venta el nombre del cliente, el nombre del vendedor si lo hubo y el
importe de la venta.
Solución:

SELECT clientes.nombre AS cliente, empleados.nombre AS vendedor, ventas.importe


FROM clientes JOIN ventas ON clientes.id=ventas.cliente LEFT JOIN
empleados ON ventas.vendedor=empleados.id;
La salida es :

+-------------+-----------------+---------+ | cliente | vendedor | importe | +-------------+-----------------+---------+ | Matt


Design | Carlos Zaltzman | 178.50 | | Diana Pérez | Carlos Zaltzman | 195.00 | | John Smith | Carlos Zaltzman | 178.50
| | Matt Design | Carlos Zaltzman | 16.00 | | Matt Design | Juan Fernández | 220.00 | | Matt Design | Carlos Zaltzman |
5.50 | | Matt Design | Juan Fernández | 11.00 | | Matt Design | Juan Fernández | 5.50 | | Diana Pérez | Carlos
Zaltzman | 200.00 | +-------------+-----------------+---------+
La primera columna es realmente Clientes.Nombre que aparece como Cliente debido al "AS Cliente" en el query. La
segunda columna, análogamente es Empleados.Nombre, pero aparece como Vendedor.

Si no se hubiesen agregado los "AS ..." las dos primeras columnas llevarían el título de "Nombre" lo que es confuso.

Es de hacer notar que hemos realizado un JOIN de 3 tablas, o si se prefiere un JOIN de Cliente con Ventas, al cual se le
ha hecho un LEFT JOIN con Empleados. Este último tenía que ser un LEFT JOIN porque pueden existir ventas que no
tienen un empleado correspondiente (Vendedor es NULL). Si hubiésemos hecho un JOIN esas ventas sin empleado
correspondiente no figurarían en el resultado.

- Igual al anterior salvo que sólo deben aparecer las ventas con importes mayores a $ 50.
Solución:

SELECT Clientes.Nombre AS Cliente, Empleados.Nombre AS Vendedor, Ventas.Importe


FROM Clientes JOIN Ventas ON Clientes.Id=Ventas.Cliente LEFT JOIN
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

Empleados ON Ventas.Vendedor=Empleados.Id WHERE Ventas.Importe > 50;

- Considerando ahora todas las ventas queremos totalizar cuánto le vendió cada vendedor a cada cliente.
Solución:

SELECT clientes.nombre AS cliente, empleados.nombre AS vendedor,


SUM(ventas.importe) AS total FROM clientes JOIN ventas ON clientes.id=ventas.cliente
LEFT JOIN empleados ON ventas.vendedor=empleados.id GROUP BY cliente,vendedor;
La salida es
+-------------+-----------------+--------+ | cliente | vendedor | total | +-------------+-----------------+--------+ | Diana Pérez
| Carlos Zaltzman | 395.00 | | John Smith | Carlos Zaltzman | 178.50 | | Matt Design | Carlos Zaltzman | 200.00 | | Matt
Design | Juan Fernández | 236.50 | +-------------+-----------------+--------+

- Este problema es una combinación de los dos anteriores. Queremos totalizar cuánto le vendió cada vendedor a cada
cliente, salvo que sólo totalizaremos las ventas de importe que superen los.
Solución:

SELECT Clientes.Nombre AS Cliente, Empleados.Nombre AS Vendedor,


SUM(Ventas.Importe) AS Total FROM Clientes JOIN Ventas ON Clientes.Id=Ventas.Cliente
LEFT JOIN Empleados ON Ventas.Vendedor=Empleados.Id WHERE Ventas.Importe > 50
GROUP BY Cliente,Vendedor;
El WHERE debe ir antes del GROUP BY.

- Ahora queremos totalizar cuánto le vendió cada vendedor a cada cliente, pero queremos listar únicamente los
TOTALES de ventas que superen los 0.
Solución:

SELECT clientes.nombre AS cliente, empleados.nombre AS vendedor,


SUM(ventas.importe) AS total FROM clientes JOIN ventas ON clientes.id=ventas.cliente
LEFT JOIN empleados ON ventas.vendedor=empleados.id GROUP BY cliente,vendedor
HAVING total > 200;
La salida es
+-------------+-----------------+--------+ | cliente | vendedor | total | +-------------+-----------------+--------+ | Diana Pérez
| Carlos Zaltzman | 395.00 | | Matt Design | Juan Fernández | 236.50 | +-------------+-----------------+--------+
Obsérvese que la cláusula HAVING va después del GROUP, al revés que el WHERE del problema anterior. Esto
es coherente con el orden en que se realizan las operaciones. En el problema anterior, MySQL primero hace el JOIN,
después selecciona las filas con Importe mayor que 50, y luego agrupa por Cliente y Vendedor. En cambio, en este
problema, después de hacer el JOIN agrupa, y luego selecciona las filas con Total mayor que 200.

- Formar una tabla que represente las ventas con los nombres de clientes, los vendedores, los importes y los artículos
vendidos.
Solución:

SELECT Clientes.Nombre AS Cliente, Empleados.Nombre AS Vendedor,


Ventas.Importe, Articulos.Nombre as Artículo FROM Clientes JOIN Ventas ON
Clientes.Id=Ventas.Cliente LEFT JOIN Empleados ON Ventas.Vendedor=Empleados.Id
JOIN Articulos ON Ventas.Articulo=Articulos.Id;
Se pueden hacer joins con cualquier número de tablas.

- Tenemos un archivo de Facturas. La legislación, con fines impositivos, requiere que estén registrados todos los
números de factura consecutivamente. Queremos comprobar si es así.
Solución:

SELECT F1.Numero+1 AS Falta FROM Facturas F1 LEFT JOIN Facturas F2 ON


F2.Numero=F1.Numero+1 WHERE F2.Numero IS NULL AND F1.NUMERO < (SELECT MAX(Numero)
FROM Facturas);
Esta solución es un ejemplo de lo que se llama un "theta join", que es simplemente un join con un cláusula ON que no
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

se refiere a la igualdad de dos columnas. En este caso, hacemos todas las combinaciones de una factura de F1 (una
copia de Facturas) y otra de F2 (otra copia) con el número siguiente. Como se trata de un LEFT JOIN, de no haber una
factura con el número siguiente, en el join va la factura de F1 seguida de columnas NULL. Pero de esas combinaciones
de filas únicamente seleccionamos el número de factura de F1 más 1 cuando el de F2 es NULL.

Es decir, cuando no hay número siguiente seleccionamos el que debería haber. La última parte del WHERE sirve para
que no se agregue a la lista de faltantes el siguiente al último número de factura del archivo.

Esta solución tiene limitaciones. Algunas son inherentes al problema planteado: no tenemos manera de saber si faltan
números de factura antes del primer número registrado o después del último. Pero la solución propuesta únicamente
encuentra el primer número de cada intervalo de números faltantes.

Por ejemplo, si los números registrados son ...,1033, 1034, 1037, 1038, 1039, 1040,.... sólo se listará 1035. No es difícil
completar manualmente el trabajo, pero se puede resolver esta dificultad completamente como se verá en el problema
8-3.

- Clientes a quienes se les ha vendido durante 3 meses consecutivos y en qué mes comienza el trimestre en que se
efectuaron dichas ventas.
Solución:

SELECT V1.Cliente, CONCAT(MONTH(V1.Fecha) ,'-',YEAR(V1.Fecha)) AS Comienzo FROM


Ventas V1 JOIN Ventas V2 ON V1.Cliente=V2.Cliente AND V1.Fecha <=
V2.Fecha AND YEAR(V2.Fecha)*12+MONTH(V2.Fecha) <
YEAR(V1.Fecha)*12+MONTH(V1.Fecha)+3 GROUP BY V1.Cliente,YEAR(V1.Fecha),MONTH(V1.Fecha)
HAVING COUNT(DISTINCT MONTH (V2.Fecha))=3;
En primer lugar se combinan todas las filas de V1 (copia de Ventas) con filas de V2 (otra copia) cuando ambas filas
se refieren al mismo cliente, la fecha de la primera fila es igual o anterior a la segunda, y el mes de la segunda fecha es
o igual al de la primera o uno de los dos siguientes.

Nota: La manera de saber si un mes de un determinado año es anterior o posterior a otro y cuántos meses de
diferencia hay entre ellos es usar la expresión YEAR(UnaFecha)*12+MONTH(Una Fecha).

Aquí Una Fecha representa una de las dos fechas que estamos comparando. Por ejemplo, consideremos el mes de
marzo (3) del 2004 y el mes de diciembre(12) de 2003.

2004*12 + 3 = 24051 2003*12 + 12 = 24048

Como 24051 - 24048 = 3, concluimos que diciembre de 2003 es 3 meses antes que marzo de 2004. Este es un "theta
join". Luego se agrupan estas combinaciones según el cliente y el mes y año de la primera fecha y por último, se
cuentan cuantos meses distintos hay en cada grupo.

Cuando hay 3 meses distintos esto significa que figuran por lo menos una vez el mes de la primera fecha y los dos
siguientes. O sea que el cliente tiene ventas en 3 meses consecutivos.

Esta solución tiene una peculiaridad : supongamos que un cliente ha efectuado compras en 4 meses consecutivos. Por
ejemplo, de enero a abril de 2004. Entonces, en la salida va a figurar el cliente con una fecha del mes de enero y otra de
febrero. Esto es correcto, en la medida que son ciertas dos afirmaciones

Se realizaron ventas enero, febero y marzo. Se realizaron ventas en febrero, marzo y abril. Hay varios puntos
interesantes más en este query: hemos usado la función CONCAT que concatena, es decir escribe uno después de otro
los resultados de varias expresiones; en este caso el mes en que comienza el trimestre, un guión y el año en que
comienza dicho trimestre de nuevo hemos usado COUNT (DISTINCT ....) para contar cuántos elementos distintos hay
en una expresión calculada en base a una columna.

Búsqueda elemental de texto


http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

A menudo tenemos columnas que son cadenas de caracteres, y queremos buscar las cadenas que contienen cierta
palabra. Esto se realiza a través de un nuevo tipo de condición: Nombre_de_columna LIKE cadena_de_caracteres.

Por ejemplo, Nombre LIKE &lsquo;Carlos&rsquo;.

Estas condiciones pueden usarse, como todas, en una cláusula WHERE o en una cláusula HAVING. La condición
Nombre_de_columna LIKE cadena_de_caracteres (donde cadena_de_caracteres no contiene ni &lsquo;%&rsquo; ni
&lsquo;_&rsquo; ) es verdadera cuando el valor de Nombre_de_columna coincide con cadena_de_caracteres (salvo que
no se distingue entre mayúsculas y minúsculas).

Veamos los valores de la condición A LIKE &rsquo;Carlos&rsquo; donde A es una columna:

Valor de la columna A

'Carlos'
Verdadera

'carlos'
Verdadera

'Carlos '
Falsa

'Juan'
Falsa

'Juan Carlos'
Falsa

Un % dentro de cadena_de_caracteres representa cualquier cadena de caracteres, incluso una sin caracteres. Entonces
A LIKE &lsquo;Carlos%&rsquo; tiene los siguientes valores:

Valor de la columna A

'Carlos'
Verdadera

'carlos'
Verdadera

'Carlos Zaltzman'
Verdadera

'Carlos '
Verdadera

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

'Juan'
Falsa

'Juan Carlos'
Falsa

Valores de A LIKE &lsquo;%Carlos&rsquo;:

Valor de la columna A

'Carlos'
Verdadera

'carlos'
Verdadera

'Juan carlos'
Verdadera

'Juan Carlos Rodríguez'


Falsa

'Juan Carlos '


Falsa

Valores de A LIKE &lsquo;%Carlos%&rsquo;:

Valor de la columna A

'Carlos'
Verdadera

'carlos'
Verdadera

' carlos '


Verdadera

'Juan Carlos Rodríguez'


Verdadera

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

'Juan'
Falsa

El carácter '_' representa un carácter cualquiera. A diferencia de &lsquo;%&rsquo; representa un carácter y uno sólo.
Luego dos&rsquo;_&rsquo; seguidos representan dos caracteres cualquiera,etc.

Valores de A LIKE &lsquo;__Carlos&rsquo;

Valor de la columna A

'Carlos'
Falsa

'12Carlos'
Verdadera

'xxCarlos'
Verdadera

' Carlos'
Verdadera

'xxcarlos'
Verdadera

'Juan Carlos'
Falsa

NOT LIKE es simplemente la negación de LIKE: es verdadera cuando LIKE es falsa y recíprocamente.

Problemas resueltos

- Listar el artículo cuyo código es 'mon20'.


Solución:

SELECT * FROM Articulos WHERE Codigo LIKE &lsquo;mon20&rsquo;;

- Hacer una lista de todos los datos de los artículos en cuyo nombre figura la palabra &lsquo;monitor&rsquo;.
Solución:
SELECT * FROM Articulos WHERE Nombre LIKE &lsquo;%monitor%&rsquo;;
Obsérvese que aunque la palabra monitor esté en la columna Nombre con mayúscula, igualmente aparece en el
resultado del query.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

- Listar todos los datos de los artículos cuyo código comience por &lsquo;mon&rsquo;.
Solución:

SELECT * FROM Articulos WHERE Codigo LIKE &lsquo;mon%&rsquo;;

- Listar los artículos cuyo código termine en &lsquo;20&rsquo;.


Solución:

SELECT * FROM Articulos WHERE Codigo LIKE &lsquo;%20&rsquo;;

- Listar los artículos cuyo código tenga exactamente dos caracteres.


Solución:

SELECT * FROM Articulos WHERE Codigo LIKE "__";


No hay ninguno. Entonces MySQL responde "Empty set", es decir, "Conjunto vacío".

- Listar todos los artículos en cuyo nombre NO figure la palabra "monitor".


Solución:

SELECT * FROM Articulos WHERE Nombre NOT LIKE "%monitor%";

Unión de dos tablas de resultados


UNION ALL indica que se haga la unión de dos resultados, simplemente escribiendo una tabla debajo de la otra. Por
ejemplo, si queremos los artículos y cantidades de las ventas a los clientes 1 y 2, basta escribir
(SELECT Articulo, Cantidad FROM Ventas WHERE Cliente=1) UNION ALL (SELECT Articulo,
Cantidad FROM Ventas WHERE Cliente=2);
UNION realiza una tarea más compleja que UNION ALL: además de unir los resultados de los queries, suprime las
filas duplicadas.

Problemas resueltos

- Listar juntas las ventas con Sucursal = 1 y las de Sucursal = 3.


Solución:

(SELECT * FROM Ventas WHERE Sucursal = 1) UNION ALL (SELECT * FROM Ventas
WHERE Sucursal = 3);
Obsérvese que como no es posible que una venta corresponda a las dos Sucursales, entonces es mejor especificar
UNION ALL, con lo que se evita el trabajo de ordenar las filas, para suprirmir las duplicaciones.

- Listar los conformes que se vencen en los próximos 30 días y los que son de más de $ 1000 y todavía no se han
vencido, sin duplicaciones.
Solución:

(SELECT * FROM Conformes WHERE Vencimiento<= DATE_ADD( CURDATE(), INTERVAL 30 DAY)


AND Vencimiento>=CURDATE()) UNION (SELECT * FROM Conformes WHERE Importe >
1000 AND Vencimiento >= CURDATE() );
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

- Volver a resolver el problema 6-10, de los números de factura faltantes, de manera que se indique para cada
intervalo faltante de cuál a cuál valor no están registradas las facturas.
Solución:

(SELECT 'Desde' AS Limite, F1.Numero+1 AS Falta FROM Facturas F1 LEFT JOIN


Facturas F2 ON F2.Numero=F1.Numero+1 WHERE F2.Numero IS NULL AND F1.NUMERO <
(SELECT MAX(Numero) FROM Facturas)) UNION ALL (SELECT 'Hasta' AS Limite, F2.Numero - 1 AS Falta
FROM Facturas F1 RIGHT JOIN Facturas F2 ON F1.Numero=F2.Numero - 1 WHERE
F1.Numero IS NULL AND F2.NUMERO > (SELECT MIN(Numero) FROM Facturas)) ORDER BY Falta,
Limite;
El query antes del UNION ALL es el mismo del problema 6-10, salvo que se agregó una columna fija llamada Limite
que siempre tiene el valor &lsquo;Desde&rsquo;, porque este query encuentra "desde" qué número faltan facturas. El
segundo query es análogo al primero. Encuentra números, después del primero, que no tienen el inmediato anterior
registrado. Esta vez la columna Limite vale &lsquo;Hasta&rsquo;.

El UNION ALL junta todas las filas obtenidas. Luego se ordenan, primero por número faltante y luego por Limite. Esto
hace que si falta una factura sola el Desde correspondiente figure antes del Hasta. Por ejemplo, dada la sucesión de
facturas 1020,1022,1025, la salida es :
+---------+-------+ | Limite | Falta | +---------+-------+ | Desde | 1021 | | Hasta | 1021 | | Desde | 1023 | | Hasta |
024 | +---------+-------+

Subqueries
Subqueries escalares
Ya antes, en la sección 4, usamos subqueries escalares. Un subquery escalar produce un sólo valor, que se usa en una
condición WHERE o HAVING.

Ejemplo: Listar los empleados que tienen salarios mayores que la mitad del salario más alto.
SELECT * FROM Empleados WHERE Salario > (SELECT MAX(Salario) FROM Empleados)/2;

IN y NOT IN

Una manera de preguntar si un valor si el valor de una columna está en una lista es usando IN.

Ejemplo: Listar las ventas efectuadas por los empleados con código 1,2.
SELECT * FROM Ventas WHERE Vendedor IN (1,2);

La lista que figura después de un IN puede obtenerse de un subquery.


SELECT * FROM Clientes WHERE Id IN (SELECT Cliente FROM Ventas);

Este query lista los Clientes a los cuáles se les han vendido algo.

NOT IN es la negación de IN. Si queremos la lista de los clientes a los que no se les han vendido nada en los últimos 30
días, escribimos
SELECT * FROM Clientes WHERE Id NOT IN ( SELECT Cliente FROM Ventas
WHERE Fecha>=DATE_SUB(CURDATE(), INTERVAL 30 DAY));

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

ALL y ANY

Podemos seleccionar filas que cumplen una condición con todas las filas de un subquery.

Ejemplo: ¿Qué conformes se vencieron después de la última factura?


SELECT * FROM Conformes WHERE Vencimiento > ALL (SELECT Fecha FROM Facturas);

También podemos seleccionar filas que cumplen una condición con alguna de las filas de un subquery.

Ejemplo: ¿Qué conformes se vencieron antes de la primera factura?

SELECT * FROM Conformes WHERE Vencimiento < ANY (SELECT Fecha FROM Facturas);
Nota: Se recomienda tener cuidado con el uso de ALL. Puede producir inestabilidad del sistema si la columna que figura
antes del ALL se escribe incorrectamente y por lo tanto no existe.

Subqueries correlacionados

Un subquery se llama correlacionado cuando hace referencia a una tabla que no figura en su cláusula FROM (aunque
sí debe figurar en un query que lo contiene).

Ejemplo: Hacer una tabla de las ventas cuyo importe es máximo dentro del artículo considerado.

SELECT Articulo, Importe FROM Ventas V1 WHERE Importe = (SELECT MAX(Importe) FROM Ventas V2
WHERE V2.Articulo = V1.Articulo) ORDER BY Articulo;

Claro que sería más sencillo, en este caso, escribir


SELECT Articulo, MAX(Importe) AS Maximo FROM Ventas GROUP BY Articulo;
Los subqueries correlacionados tienden a ser ineficientes con tablas grandes, aunque a menudo MySQL reformula
internamente el query y lo hace eficiente.

EXISTS y NOT EXISTS

A menudo lo único que interesa de un subquery correlacionado es saber si tiene alguna fila o no. Para eso tenemos
EXISTS y NOT EXISTS.

Por ejemplo, si queremos seleccionar todas las Sucursales en las que se hizo alguna venta,
SELECT * FROM Sucursales WHERE EXISTS (SELECT 1 FROM Ventas WHERE Sucursal
= Sucursales.Id);

El SELECT 1 es para enfatizar que no nos interesa el contenido de las filas del subquery sino si existen o no. Si
ejecutamos el subquery por sí mismo, con un valor apropiado en vez de Sucursales.Id, obtenemos una columnas de
unos. Esta tabla tiene tantas filas como filas de Ventas hay con la Sucursal indicada.

En este caso también hubiese podido evitarse el subquery correlacionado con :

SELECT DISTINCT Sucursales.* FROM Sucursales JOIN Ventas ON Sucursales.Id =


Ventas.Sucursal;

Si queremos las Sucursales donde no se hizo una venta, podemos usar


SELECT * FROM Sucursales WHERE NOT EXISTS (SELECT 1 FROM Ventas WHERE
Sucursal = Sucursales.Id);

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

o también
SELECT DISTINCT Sucursales.* FROM Sucursales LEFT JOIN Ventas ON
Sucursales.Id = Ventas.Sucursal WHERE Ventas.Id IS NULL;

Problemas resueltos

- Listar las Ventas que hayan sido facturadas;


Solución:
SELECT * FROM Ventas WHERE Id IN (SELECT Venta FROM Lineas_Factura);

- Listar las Ventas que falte facturar.


Solución:
SELECT * FROM Ventas WHERE Id NOT IN (SELECT Venta FROM Lineas_Factura);

- Ventas posteriores a la última factura.


Solución:

SELECT * FROM Ventas WHERE Fecha > ALL (SELECT Fecha FROM Facturas);
Es equivalente a
SELECT * FROM Ventas WHERE Fecha > (SELECT MAX(Fecha ) FROM Facturas);
De hecho, aunque se solicite el primer query, MySQL, internamente, ejecuta el 2º., que es mucho más eficiente.

- Artículos que no se han vendido, para cada región, en el último año.


Solución:

SELECT Articulos.Nombre, Sucursales.Descripcion FROM Articulos, Sucursales WHERE NOT


EXISTS (SELECT 1 FROM Ventas WHERE Sucursal = Sucursales.Id AND
Articulo = Articulos.Id AND Fecha > DATE_SUB(CURDATE(), INTERVAL 365 DAY)) ORDER
BY 1, 2;
Este es un ejemplo de un subquery correlacionado. En efecto, dos columnas del query exterior, Sucursales.Id y
Articulos.Id, figuran en el subquery. MySQL va combinando todas las Sucursales con todos los artículos y seleccionando
aquellas combinaciones para las cuales no hay ventas correspondientes.

El SELECT 1 del subquery no tiene importancia, lo que realmente hace MySQL es averiguar si hay alguna fila de Ventas
que cumpla la cláusula WHERE, para darle un valor al NOT EXISTS. Si hay una fila que cumple el WHERE Sucursal...,
entonces el NOT EXISTS es falso, etc.

El SELECT 1 puede sustituirse por cualquier otro SELECT, que quizás resulte más intuitivo. El funcionamiento será el
mismo.

- Clientes a los que se les han hecho menos de tres ventas en los últimos 365 días.
Solución:

SELECT * FROM Clientes WHERE 3 > (SELECT COUNT(*) FROM Ventas


WHERE Fecha > DATE_SUB(CURDATE(), INTERVAL 365 DAY) AND Cliente=Clientes.Id);
Otro ejemplo de subquery correlacionado. El subquery calcula el número de ventas que se le ha hecho a cada
cliente en el último año. Cuando el número es menor que 3, entonces se selecciona la fila de clientes.

- Artículos que se han vendido en todas las sucursales.


Solución:

SELECT Nombre FROM Articulos WHERE NOT EXISTS( SELECT 1 FROM Sucursales
WHERE NOT EXISTS (SELECT 1 FROM Ventas WHERE
http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59
Ing. Alejandro Sueldo

Sucursal=Sucursales.Id AND Articulo=Articulos.Id)) ORDER BY 1;


Lo que se trata de lograr podría expresarse así :
SELECCIONAR Nombre DE Articulos CUANDO PARA TODA Sucursal EXISTE Venta de
Articulo en Sucursal.
El problema es " CUANDO PARA TODA Sucursal..." que no tiene una traducción directa a MySQL, ni a ningún SQL
que yo conozca. Pero esta expresión es equivalente a "NO EXISTE Sucursal TAL QUE NO...". Es decir, afirmar que algo
se cumple para todas las Sucursales equivale a afirmar que no existe una región para la que no se cumpla. Resultaría :

SELECCIONAR Nombre DE Articulos CUANDO NO EXISTE Sucursal TAL QUE NO EXISTE


Venta de Articulo en Sucursal.
El query es traducción directa a MySQL de este seudocódigo.

- Vendedores que hayan vendido todos los artículos a la venta en el último año (los últimos 365 días).
Solución:

SELECT * FROM Empleados WHERE NOT EXISTS (SELECT 1 FROM Articulos


WHERE NOT EXISTS ( SELECT 1 FROM Ventas WHERE
Ventas.Vendedor=Empleados.Id AND Ventas.Articulo=Articulos.Id AND
Fecha> DATE_SUB(CURDATE(), INTERVAL 365 DAY)));
Este problema es análogo al anterior. Se ha incluido con el propósito que el lector repita el análisis del problema
anterior.

- Vendedores que hayan vendido por lo menos un artículo de cada grupo en el último año.
Solución:

SELECT * FROM Empleados WHERE NOT EXISTS ( SELECT 1 FROM Grupos


WHERE NOT EXISTS ( SELECT 1 FROM Articulos WHERE Grupo=Grupos.Id
AND EXISTS ( SELECT 1 FROM Ventas WHERE
Articulo=Articulos.Id AND Vendedor=Empleados.Id AND
Fecha>DATE_SUB(CURDATE(), INTERVAL 365 DAY))));)));
Podríamos escribir el siguiente seudocódigo :
SELECCIONAR * DE Empleados DONDE PARA TODO Grupo EXISTE Articulo en Grupo
TAL QUE EXISTE Venta DEL Empleado y Articulo EN ultimo año.
Como no tenemos una manera directa de representar el PARA TODO, usamos la equivalencia de los problemas
anteriores. Resulta,
SELECCIONAR * DE Empleados DONDE NO EXISTE Grupo TAL QUE NO EXISTE Articulo
en Grupo TAL QUE EXISTE Venta DEL Empleado y Articulo EN ultimo año.
El resto es una traducción directa.

- Grupos de los cuales no se vendieron artículos en el último año, para cada vendedor, ordenado alfabéticamente por
vendedor y grupo.
Solución:

SELECT Empleados.Nombre, Grupos.Descripcion FROM Empleados, Grupos WHERE


NOT EXISTS( SELECT 1 FROM Ventas WHERE Vendedor = Empleados.Id AND
Fecha>DATE_SUB(CURDATE(), INTERVAL 365 DAY) AND EXISTS ( SELECT 1 FROM
Articulos WHERE Id = Ventas.Articulo AND Grupo = Grupos.Id)) ORDER BY 1, 2;
Seudocódigo :
SELECCIONAR Vendedor, Grupo DE Empleados, Grupos DONDE NO EXISTE Venta TAL
QUE Venta corresponde a Vendedor Y es del último año Y el Articulo de la Venta es del Grupo.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

Salida a Excel
El programa mysql, en el que ingresamos los queries, no permite ver resultados grandes claramente. Los problemas
vistos tenían soluciones con pocas filas y columnas. ¿ Qué hacemos si tenemos 1000 filas y 30 columnas?

Una solución, no muy buena, es pasar la salida del query a texto. Esto se realiza agregando después de la cláusula
SELECT (exterior, si hay subqueries) una cláusula INTO OUTFILE path.

Por ejemplo, para que el resultado se guarde en un archivo c:\MySQL\bin\p\salida.txt (c:\MySQL\bin\p es el directorio
donde hemos supuesto que guardaron los problemas resueltos) debemos escribir
SELECT ... INTO OUTFILE 'c:/MySQL/bin/p/salida.txt' LINES TERMINATED BY '\r\n' FROM ...
La última línea es característica de Windows, donde el final de cada línea se indica por dos caracteres (invisibles)
mientras que en Unix, el final de cada línea se indica por un solo carácter.

Obsérvese que el camino (path) del archivo va con barras : / . Mientras que la cláusula LINES TERMINATED lleva
contrabarras : \ .

Para que el procedimiento funcione es imprescindible que el directorio donde se va a guardar la salida exista. MySQL
crea el archivo pero no el directorio. También es imprescindible que el archivo no exista. Si existe, aparecerá un
mensaje de error. Si se observa el texto obtenido con cualquier procesador (Bloc de notas, WordPad, Word) se verá
que hay problemas : salvo en el Bloc de notas las columnas no aparecen bien alineadas ( y el bloc de notas tiene
limitaciones en lo que se refiere al tamaño del archivo que puede manejar).
Las vocales con tilde se cambian por otros caracteres.

Para resolver estos problemas se puede usar Microsoft Excel. Usando Excel 97 empezamos abriendo el archivo
(teniendo cuidado de seleccionar &lsquo;Archivos de texto&rsquo; en &lsquo;Tipo de Archivo&rsquo; ). A continuación
aparecen varios cuadros de diálogo.

- El primero tiene título &lsquo;Asistente para importar texto &ndash; paso 1 de 3&rsquo;. A media altura, a la derecha,
donde dice &lsquo;Origen del archivo:&rsquo; se debe seleccionar &lsquo;DOS u OS/2 (PC-8)&rsquo;. Si no están
seleccionados, seleccionar además &lsquo;Delimitados&rsquo; y &lsquo; Comenzar a importar en la fila : 1&rsquo;.
Hacer click en el botón &lsquo;Siguiente>&rsquo;.

- En el segundo cuadro de diálogo asegurarse que estén seleccionados &lsquo;Tabulación&rsquo; en


&lsquo;Separadores&rsquo; y &lsquo;&rsquo; en &lsquo;Calificador de texto&rsquo;. Luego hacer click en el botón
&lsquo;Siguiente>&rsquo;.

- En el tercer cuadro de diálogo asegurarse que esté seleccionado &lsquo;General&rsquo; en &lsquo;Formato de los
datos en columnas&rsquo; y por último hacer click en el botón &lsquo;Terminar&rsquo;.

Para disponer de una planilla Excel del tipo usual ir al menú &lsquo;Archivo&rsquo; y seleccionar &lsquo;Guardar
como&rsquo;.

En el cuadro de diálogo que aparece seleccionar en &lsquo;Guardar como tipo: &lsquo; la opción &lsquo;Libro de
Microsoft Excel (*.xls)&rsquo;. Luego hacer click en el botón &lsquo;Guardar&rsquo;.

Se creará una planilla Excel con el mismo nombre del archivo de texto, pero con terminación &lsquo;xls&rsquo;. En este
caso, sería &lsquo;salida.xls&rsquo;.

Esta vez tenemos una columna de Excel por cada columna del query y las vocales con tilde se ven correctamente.

Lo que sí hay que agregar manualmente son los títulos de las columnas.

Nota : los NULL aparecen como &lsquo;\N&rsquo;.

El funcionamiento de SELECT
Ahora que hemos visto unos cuantos queries, podemos preguntarnos cómo funciona SELECT. Es un proceso formado
por varias etapas sucesivas :

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

- FROM: Aquí se realizan los JOINS o un subquery.

- WHERE: De las filas resultantes del FROM se separan las que cumplen las condiciones especificadas en el WHERE.

- GROUP BY: Las filas se ordenan y agrupan según las columnas especificadas.

- SELECT : Ahora a partir de las filas que han resultado de los pasos anteriores, se construyen otras según las
expresiones que figuren en el SELECT. Si hay un GROUP BY sólo se construye una fila por cada grupo de filas del
GROUP BY. Cuidado :en caso que haya valores distintos de una columna seleccionada dentro de un grupo, se
selecciona un valor cualquiera al azar.

- Si hay un DISTINCT, se eliminan las duplicaciones de filas.

- HAVING: Vuelven a descartarse filas que no cumplan con la condición de esta cláusula.

- ORDER BY : Se ordenan las filas, por el criterio indicado.

- LIMIT : Si hay más filas de las indicadas por esta cláusula, se descartan.

- UNION : Se unen los resultados de varios queries. Puede haber un ORDER BY y un LIMIT después del UNION.

- Nota final sobre eficiencia: Para bases de datos chicas, con algunos miles de filas, normalmente no hay grandes
problemas de eficiencia. Con todo, si algún query es muy lento, eso no quiere decir que el problema sea
intrínsecamente demasiado complicado para el computador. Los tiempos en que se ejecutan los queries varían
muchísimo según los detalles de la base de datos y los detalles de los queries mismos. O sea que si hay problemas de
velocidad, es recomendable consultar con un programador con experiencia en SQL.

Glosario

Como el SQL es a menudo comprensible aún para personas que no lo han estudiado, pero que hablan inglés, parece
útil tener un pequeño diccionario.

TérminoDescripción

ALL
Todos.

ANY
Cualquier.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

AS
Como.

AVG
Cualquier.

ANY
Abreviatura de AVERAGE, promedio.

COUNT
Contar.

CURDATE()
Función SQL. Abreviatura de CURRENT DATE, fecha de hoy.

DATE
Fecha.

DATE_ADD()
Función SQL. Literalmente, fecha sumar.

DATE_SUB()
Función SQL. Literalmente, fecha restar.

DAY
Día.

DAYNAME()
Función SQL, de DAY, día y NAME, nombre.

DAYOFWEEK()
Función SQL, concatenación de DAY OF WEEK, día de la semana.

DESC
Abreviatura de 'descending' , que puede traducirse como 'en sentido descendiente'. Se refiere a ordenar en
sentido descendente.

DISTINCT
Distintos.

EXISTS
Existe.

FROM
De.

IN
En.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

IS
Es.

JOIN
Literalmente unión, zona de contacto. En SQL, representa una manera especial de unir dos tablas.
Matemáticamente, es un subconjunto de un producto cartesiano..

LEFT JOIN
Expresión usada en SQL. Literalmente, unión izquierda.

LIKE
Parecido a.

MAX
Abreviatura de MAXIMUM, máximo.

MIN
Abreviatura de MINIMUM, mínimo.

MONTH
Mes.

NAME
Nombre.

NOT
No.

NOT IN
No en, no pertenece a.

NULL
NULO, pero en un sentido especial, no se refiere al número 0, sino a un valor desconocido.

ON
Sobre. En SQL indica una condición en un JOIN.

ORDER BY
Ordenar por.

RIGHT JOIN
Expresión usada en SQL. Literalmente, unión derecha.

RIGHT()
Funcion SQL. Right significa derecha.

SELECT
Seleccionar.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

SHOW
Mostrar, usado en SHOW TABLES (Mostrar tablas) y SHOW DATABASES (Mostrar bases de datos).

SUM
Sumar.

TABLE
Tabla.

UNION
Unión.

WHERE
Donde.

YEAR
Año.

Autor: Carlos Zaltzman


Fecha publicación: 30 Enero del 2005

Fuente: MySQL Hispano. http://www.mysql-hispano.org/page.php?id=31&pag=14

Bibliografía

- Rudy Limeback, Ask the Expert,


http://searchdatabase.techtarget.com/originalContent/0,289142,sid13_gci950920,00.html
Muchos problemas de este tutorial se basan en ideas del Sr. Limeback.

- Reference Manual for version 5.0.1-alfa, MySQL AB, http://dev.mysql.com/doc. En esta página encontrará las
instrucciones para conseguir el manual.

- J. Benavides Abajo, J.M. Olaizola Bartolomé, E. Rivero Cornelio, SQL Para usuarios y programadores, Paraninfo
S.A., Madrid, 1991.

- MySQL Internals Manual for version 4.1.7, MySQL AB. Para obtener este manual deberá obtener una distribución de
MySQL con fuentes (source version) y encontrará el archivo internals.texi en el directorio Docs de la distribución. Para
obtener esa distribución seguir las instrucciones de http://www.mysql.com/downloads. Advertencia: este manual es
altamente técnico y requiere Unix para ser leído con facilidad.

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59


Ing. Alejandro Sueldo

http://alejandrosueldo.com.ar/joomla Potenciado por Joomla! Generado: 3 September, 2010, 02:59

You might also like