O MySQL fornece várias funções que você pode usar para realizar cálculos em datas, por exemplo, para calcular idades ou extrair partes de datas.
Para determinar quantos anos cada um do seus animais tem, compute a diferença do ano da data atual e a data de nascimento (birth), depois subtraia se a o dia/mês da data atual for anterior ao dia/mês da data de nascimento. A consulta seguinte, mostra, para cada animal, a data de nascimento, a data atual e a idade em anos.
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 | +----------+------------+------------+------+
Aqui, YEAR()
separa a parte do ano de uma
data e RIGHT()
separa os cinco caracteres
mais a direita que representam a parte da data
MM-DD
. A parte da expressão que compara os
valores MM-DD
resulta em 1 ou 0, o qual
ajusta a diferença do ano um ano abaixo se
CURDATE
ocorrer mais cedo, no ano, que
birth
. A expressão completa é um tanto
deselegante, então um apelido (age
) é
usado para obter uma saída mais significativa.
A consulta funciona, mas o resultado pode ser mais
compreensível se os registros forem apresentados em alguma
ordem. Isto pode ser feito adicionando uma cláusula
ORDER BY name
para ordenar a saída pelo
nome:
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 a saída por age
em vez de
name
, é só utilizar uma cláusua
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 | +----------+------------+------------+------+
Uma consulta similar pode ser usada para determinar a idade na
morte para animais que morreram. Para determinar quais são os
animais, confira se o valor de death
não
é NULL
. Depois para estes com valores
não-NULL
, compute a diferença entre os
valores dos campos death
e
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 | +--------+------------+------------+------+
A consulta usa death IS NOT NULL
em vez de
death != NULL
porque
NULL
é um valor especial que não pode ser
comparada usando operadores comuns de comparação. Isto será
explicado depois. See Secção 3.3.4.6, “Trabalhando com Valores Nulos (NULL
)”.
E se você desejar saber quais animais fazem aniversário no
próximo mês? Para este tipo de cálculo, ano e dia são
irrelevantes; você simplesmente deseja extrair a parte do
mês da coluna birth
. O MySQL fornece
diversas funções para extrair partes da data, como em
YEAR()
, MONTH()
e
DAYOFMONTH()
. MONTH
é a
função apropriada aqui. Para ver como ela funciona, execute
uma consulta simples que mostre o valor de
birth
e 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 animais com aníversário no próximo mês também
é fácil. Suponha que o mês atual é abril. Então o valor
do mês é 4
e você procura por animais
nascidos em Maio (mês 5
) assim:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
+-------+------------+
| name | birth |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+
Existe uma pequena complicação se o mês atual é Dezembro,
é claro. Você não pode apenas adicionar um para o número
do mês (12
) e procurar por animais
nascidos no mês 13
, porque não existe tal
mês. O certo seria procurar por animais nascidos em Janeiro
(mês 1
).
Você pode também escrever uma consulta para que funcione sem
importar qual é o mês atual. Assim você não têm quee usar
um número de mês em particular na consulta.
DATE_ADD()
permite adicionar um intervalo
de tempo para uma data fornecida. Se você adicionar um mês
para o valor de CURDATE
, então extrair a
parte do mês com MONTH()
, o resultado é o
mês no qual você deseja procurar por aniversários:
mysql>SELECT name, birth FROM pet
->WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(), INTERVAL 1 MONTH));
Uma maneira diferente para realizar a mesma tarefa é
adicionar 1
para obter o mês seguinte ao
atual (depois de usar a função módulo
(MOD
) para o valor do mês retornar
0
se ele for 12
):
mysql>SELECT name, birth FROM pet
->WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
Perceba que MONTH
retorna um número entre
1
e 12
. E
MOD(alguma_coisa,12)
retorna um número
entre 0
e 11
. Então a
adição tem que ser feita depois do MOD()
,
senão iríamos de Novembro (11
) para
Janeiro (1
).
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.