MySQL provee varias funciones que se aplican a cálculos entre fechas, por ejemplo, para calcular edades u obtener partes de una fecha.
Para determinar cuántos años de edad tiene cada mascota, hay que calcular la diferencia entre el año de la fecha actual y el de la fecha de nacimiento, y luego restar 1 al resultado si el dia y mes actuales son anteriores al día y mes indicados por la fecha de nacimiento. La siguiente consulta devuelve, para cada mascota, el nombre, la fecha de nacimiento, la fecha actual, y la edad en años.
mysql> SELECT name, birth, CURDATE(),
    -> (YEAR(CURDATE())-YEAR(birth))
    -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet;
+----------+------------+------------+------+
| name     | birth      | CURDATE()  | age  |
+----------+------------+------------+------+
| Fluffy   | 1993-02-04 | 2003-08-19 |   10 |
| Claws    | 1994-03-17 | 2003-08-19 |    9 |
| Buffy    | 1989-05-13 | 2003-08-19 |   14 |
| Fang     | 1990-08-27 | 2003-08-19 |   12 |
| Bowser   | 1989-08-31 | 2003-08-19 |   13 |
| Chirpy   | 1998-09-11 | 2003-08-19 |    4 |
| Whistler | 1997-12-09 | 2003-08-19 |    5 |
| Slim     | 1996-04-29 | 2003-08-19 |    7 |
| Puffball | 1999-03-30 | 2003-08-19 |    4 |
+----------+------------+------------+------+
          En el ejemplo anterior, YEAR() trae la
          parte correspondiente al año de una fecha, y
          RIGHT() trae los 5 primeros caracteres
          contando desde la derecha, que representan la parte
          MM-DD de la fecha. La porción de la
          expresión que compara los valores MM-DD
          devuelve 1 o 0, lo cual se corresponde con la diferencia de 1
          año a restar de la edad si el dia de la fecha devuelto por
          CURDATE() ocurre antes que la fecha de
          nacimiento birth. La expresión completa es
          un tanto confusa para usar como encabezado, por lo que se
          emplea un alias (age)
          para que el encabezado sea más comprensible.
        
          La consulta funciona bien, pero los resultados podrían
          revisarse más fácilmente si las filas se presentaran en
          algún orden. Esto puede hacerse agregando la cláusula
          ORDER BY name para ordenar por nombre la
          salida:
        
mysql> SELECT name, birth, CURDATE(),
    -> (YEAR(CURDATE())-YEAR(birth))
    -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet ORDER BY name;
+----------+------------+------------+------+
| name     | birth      | CURDATE()  | age  |
+----------+------------+------------+------+
| Bowser   | 1989-08-31 | 2003-08-19 |   13 |
| Buffy    | 1989-05-13 | 2003-08-19 |   14 |
| Chirpy   | 1998-09-11 | 2003-08-19 |    4 |
| Claws    | 1994-03-17 | 2003-08-19 |    9 |
| Fang     | 1990-08-27 | 2003-08-19 |   12 |
| Fluffy   | 1993-02-04 | 2003-08-19 |   10 |
| Puffball | 1999-03-30 | 2003-08-19 |    4 |
| Slim     | 1996-04-29 | 2003-08-19 |    7 |
| Whistler | 1997-12-09 | 2003-08-19 |    5 |
+----------+------------+------------+------+
          Para ordenar la salida por edad (age) en
          lugar de por nombre (name), solo hay que
          utilizar una cláusula ORDER BY diferente:
        
mysql> SELECT name, birth, CURDATE(),
    -> (YEAR(CURDATE())-YEAR(birth))
    -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet ORDER BY age;
+----------+------------+------------+------+
| name     | birth      | CURDATE()  | age  |
+----------+------------+------------+------+
| Chirpy   | 1998-09-11 | 2003-08-19 |    4 |
| Puffball | 1999-03-30 | 2003-08-19 |    4 |
| Whistler | 1997-12-09 | 2003-08-19 |    5 |
| Slim     | 1996-04-29 | 2003-08-19 |    7 |
| Claws    | 1994-03-17 | 2003-08-19 |    9 |
| Fluffy   | 1993-02-04 | 2003-08-19 |   10 |
| Fang     | 1990-08-27 | 2003-08-19 |   12 |
| Bowser   | 1989-08-31 | 2003-08-19 |   13 |
| Buffy    | 1989-05-13 | 2003-08-19 |   14 |
+----------+------------+------------+------+
          Una consulta similar se utiliza para determinar la edad a la
          fecha de muerte de los animales. Se determinan los animales
          que han muerto verificando si el valor de la columna
          death es NULL. Entonces,
          para todos los valores no NULL calcula la
          diferencia entre las fechas de muerte
          (death) y nacimiento
          (birth):
        
mysql> SELECT name, birth, death,
    -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet WHERE death IS NOT NULL ORDER BY age;
+--------+------------+------------+------+
| name   | birth      | death      | age  |
+--------+------------+------------+------+
| Bowser | 1989-08-31 | 1995-07-29 |    5 |
+--------+------------+------------+------+
          La consulta utiliza la expresión death IS NOT
          NULL en lugar de death <>
          NULL porque NULL es un valor
          especial, que no puede ser comparado mediante los operadores
          lógicos habituales. Este tema se trata más extensamente más
          adelante. Consultar Sección 3.3.4.6, “Trabajar con valores NULL”.
        
          ¿Qué tal si se quisiera saber qué animales cumplen años el
          próximo mes? Para esta clase de cálculos, el año y el día
          son irrelevantes; simplemente se desea extraer de la columna
          birth la parte correspondiente al mes.
          MySQL cuenta con varias funciones para extraer partes de
          fechas, como YEAR(),
          MONTH(), y DAYOFMONTH().
          MONTH() es la función apropiada para este
          caso. Para verla en funcionamiento, ejecute una consulta que
          muestra tanto el valor de birth como el de
          MONTH(birth):
        
mysql> SELECT name, birth, MONTH(birth) FROM pet; +----------+------------+--------------+ | name | birth | MONTH(birth) | +----------+------------+--------------+ | Fluffy | 1993-02-04 | 2 | | Claws | 1994-03-17 | 3 | | Buffy | 1989-05-13 | 5 | | Fang | 1990-08-27 | 8 | | Bowser | 1989-08-31 | 8 | | Chirpy | 1998-09-11 | 9 | | Whistler | 1997-12-09 | 12 | | Slim | 1996-04-29 | 4 | | Puffball | 1999-03-30 | 3 | +----------+------------+--------------+
          Encontrar los animales que cumplen años el mes siguiente es
          también sencillo. Suponga que el mes actual es abril. De modo
          que su número es 4, y se buscan los
          animales nacidos en Mayo (mes 5), de esta
          forma:
        
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+ | name | birth | +-------+------------+ | Buffy | 1989-05-13 | +-------+------------+
          Esto se complica ligeramente cuando el mes actual es
          Diciembre. No se puede simplemente sumarle 1 al número del
          mes (12) y buscar animales nacidos en el
          mes 13, porque no existe tal mes. En lugar
          de eso, se debe buscar por animales nacidos en Enero (mes
          1).
        
          Se puede incluso escribir la consulta de forma que funcione
          sin importar cual es el mes actual. Así, no se necesitará
          indicar un mes en particular en la consulta.
          DATE_ADD() sirve para sumar un intervalo de
          tiempo a una fecha dada. Si se adiciona un mes al valor de
          CURDATE(), y se extrae el mes mediante
          MONTH(), el resultado será el mes en el
          que se buscarán cumpleaños:
        
mysql> SELECT name, birth FROM pet
    -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
          Una manera alternativa de alcanzar el mismo resultado es sumar
          1 al mes actual para obtener el mes
          siguiente (después de emplear la función módulo
          (MOD) para dejar el número de mes en
          0 si resultara ser 12:
        
mysql> SELECT name, birth FROM pet
    -> WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
          Advierta que MONTH devuelve un número
          entre 1 y 12. Y
          MOD(algun_valor,12) devuelve un número
          entre 0 y 11. La suma
          debe ser realizada después de MOD(), en
          otro caso se estaría pasando de Noviembre
          (11) a Enero (1).
        
Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.

