2009年12月1日(mysql_6)

来源:互联网 发布:mac图片处理软件 编辑:程序博客网 时间:2024/04/29 13:21

3.3.4.5..数据计算

MySQL提供很多函数,那样你能对数据执行各种运算,例如,计算年龄或提取日期部分。

为了明确你的动物是多少岁,计算当年年份和出生日期的年份的不同,然后除去当前在日历上的时间中年份比出生日期早,接下来为每个宠物显示,出生日期,当前日期,和年龄。

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 |+----------+------------+------------+------+

这里,YEAR()从日期中取出年份并且RIGHT()去掉最右边的五个反应日期中MM-DD(年日历)。与MM-DD值比较求值01的表达式的这部分是为了适应同一年中当前日期又比出生日期早。那完整的表达式有点笨拙,所以别名(age)被用来作为输出的行标更有意义。

那查询起作用了,但是如果行可以按照一些顺序呈现,结果就可能更容易被浏览。这可能需要添加ORDER BY name子句来用名字来摆放输出的结果:

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 |+----------+------------+------------+------+

age而不是name摆放结果,仅仅只用用不同的ORDER BY子句:

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 |+----------+------------+------------+------+

一个比较简单的查询能被用来明确已经死亡的动物的年龄。你指出这些被检查death是否为null的动物。然后对不是null的值,计算出deathbirth值的差异:

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 |+--------+------------+------------+------+

这查询用的是death IS NOT NULL而不是death<>NULL因为NULL是一个特定的值不能用一般的比较间隔符比较。这以后讨论参考Section 3.3.4.6, “Working with NULL Values”.

如果你想知道什么动物下个月过生日该做什么?对这种计算,年和日是无关的,你简单的只需要提取月份从birth列中,像YEAR(),MONTH(),DAYOFMONTH(),MONTH()是这里可选择的函数。为了看看它是如何工作的,运行一个简单的查询显示birthMONTH(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 |+----------+------------+--------------+

发现即将下个月动物的生日是很简单的,设想,下个月是四月。然后month值是4,你能查找5月的动物像这样:

mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;+-------+------------+| name  | birth      |+-------+------------+| Buffy | 1989-05-13 |+-------+------------+

有点麻烦的是如果当前月是December。你基本不可以添加一个12月份的并寻找13月出生的动物,因为没有这样的月份。因此你要选择JanuaryMonth 1)。

你能写一个查询以至于它的作用不依赖当前月份是多少,以至于你不用使用特定月份的数字。DATE_ADD()允许你添加一个于指定时间间隔一段时间。如果你添加一个月为每个CURDATE(),然后执行月份部分用MONTH(),那结果就可以产生寻找的生日:

Mysql>SELECT name,birth FROM pet

->WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));

一个不同方式完成一样加一得到当前时间的下个月份的任务的同样可以使用方法(MOD)去包装月份值为0如果现在是12月时:

Mysql>SELECT name,birth FROM pet

->WHERE MONTH(birth) = MOD(MONTH(CURDATE()),12)+1;

注意MONTH()返回的一个从112之间的数。并且MOD(something,12)返回一个011之间的数。所以要在MOD()后加上1,否则我们将从Noverber11)直接跳到January1)。

3.3.4.6.NULL值的作用

NULL值直到你使用过它都是很疑惑的。概念上,NULL是一个迷失的不知道的值并且它被看待与其他值有些不同。测试NULL,你不能使用任何数学比较法像=<>.用下面的查询证明一下:

mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;+----------+-----------+----------+----------+| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |+----------+-----------+----------+----------+|     NULL |      NULL |     NULL |     NULL |+----------+-----------+----------+----------+

很清楚你不能总这些比较中得到有意义的结果,用IS NULLIS NOT NULL表达代替:

mysql> SELECT 1 IS NULL, 1 IS NOT NULL;+-----------+---------------+| 1 IS NULL | 1 IS NOT NULL |+-----------+---------------+|         0 |             1 |+-----------+---------------+

注意在mysql中,0NULL都意味着false而其他的都意味着true。在布尔(boolean)操作符中默认的真值是1.

NULL有特别的待遇的原因在接下来的部分,它是很必要确定动物不再活着使用death IS NOT NULL替代death<>NULL.

两个NULL值在GROUP BY中是被看待相等的。

当做ORDER BY时,NULL被至于第一个在ORDER BY...ASC和最后在ORDER BY ...DESC

当用NULL一个普遍的错误是假设不可能添加一个零或空字符串在默认NOT NULL的列中,但是这是不可能。实际上存在这些值,但是NULL意味着没有值。你可以容易的测试用IS[NOT] NULL

mysql> SELECT 0 IS NULL, 0 IS NOT NULL, '' IS NULL, '' IS NOT NULL;+-----------+---------------+------------+----------------+| 0 IS NULL | 0 IS NOT NULL | '' IS NULL | '' IS NOT NULL |+-----------+---------------+------------+----------------+|         0 |             1 |          0 |              1 |+-----------+---------------+------------+----------------+

因此向一个NOT NULL列中插入一个零或空字符串,事实上这些都是NOT NULL.参考Section B.1.5.3, “Problems with NULL Values”.