Mysql从表中检索信息:修订间差异
无编辑摘要 |
无编辑摘要 |
||
第165行: | 第165行: | ||
| Bowser | dog | 1989-08-31 | | | Bowser | dog | 1989-08-31 | | ||
+--------+---------+------------+ | +--------+---------+------------+ | ||
===对行排序=== | |||
你可能已经注意到在前面的例子中,结果行的显示顺序是没有特定顺序的。当行按某种有意义的方式排序时,检查查询结果更容易。要对结果进行排序,使用ORDER BY子句。 | |||
下面是按日期排序的动物生日: | |||
mysql> SELECT name, birth FROM pet ORDER BY birth; | |||
+----------+------------+ | |||
| name | birth | | |||
+----------+------------+ | |||
| Buffy | 1989-05-13 | | |||
| Bowser | 1989-08-31 | | |||
| Fang | 1990-08-27 | | |||
| Fluffy | 1993-02-04 | | |||
| Claws | 1994-03-17 | | |||
| Slim | 1996-04-29 | | |||
| Whistler | 1997-12-09 | | |||
| Chirpy | 1998-09-11 | | |||
| Puffball | 1999-03-30 | | |||
+----------+------------+ | |||
在字符类型的列上,排序(就像所有其他比较操作一样)通常以不区分大小写的方式进行。这意味着对于除了大小写不同的列,排序是未定义的。您可以通过使用BINARY来强制对列进行区分大小写排序,如下所示:ORDER BY BINARY col_name。 | |||
默认的排序顺序是升序,最小值排在前面。要按相反(降序)顺序排序,请在要排序的列的名称后面添加DESC关键字: | |||
mysql> SELECT name, birth FROM pet ORDER BY birth DESC; | |||
+----------+------------+ | |||
| name | birth | | |||
+----------+------------+ | |||
| Puffball | 1999-03-30 | | |||
| Chirpy | 1998-09-11 | | |||
| Whistler | 1997-12-09 | | |||
| Slim | 1996-04-29 | | |||
| Claws | 1994-03-17 | | |||
| Fluffy | 1993-02-04 | | |||
| Fang | 1990-08-27 | | |||
| Bowser | 1989-08-31 | | |||
| Buffy | 1989-05-13 | | |||
+----------+------------+ | |||
您可以按多个列进行排序,还可以按不同的方向排序不同的列。例如,要按动物类型升序排序,然后按动物类型内的出生日期降序排序(最年轻的动物排在前面),使用以下查询: | |||
mysql> SELECT name, species, birth FROM pet | |||
ORDER BY species, birth DESC; | |||
+----------+---------+------------+ | |||
| name | species | birth | | |||
+----------+---------+------------+ | |||
| Chirpy | bird | 1998-09-11 | | |||
| Whistler | bird | 1997-12-09 | | |||
| Claws | cat | 1994-03-17 | | |||
| Fluffy | cat | 1993-02-04 | | |||
| Fang | dog | 1990-08-27 | | |||
| Bowser | dog | 1989-08-31 | | |||
| Buffy | dog | 1989-05-13 | | |||
| Puffball | hamster | 1999-03-30 | | |||
| Slim | snake | 1996-04-29 | | |||
+----------+---------+------------+ | |||
DESC关键字仅适用于紧随其后的列名(birth),它不影响species列的排序顺序。 | |||
===日期计算=== | |||
MySQL提供了几个函数,可用于对日期进行计算,例如计算年龄或提取日期的部分。 | |||
要确定每只宠物的年龄,可以使用TIMESTAMPDIFF()函数。它的参数是要表示结果的单位,以及要计算差异的两个日期。以下查询显示了每只宠物的出生日期、当前日期和年龄(以年为单位)。使用别名(age)使最终输出列的标签更有意义。 | |||
mysql> SELECT name, birth, CURDATE(), | |||
TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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 | | |||
+----------+------------+------------+------+ | |||
该查询可以工作,但如果按某种顺序呈现行,则结果可以更容易地扫描。可以通过添加ORDER BY name子句来按名称对输出进行排序: | |||
mysql> SELECT name, birth, CURDATE(), | |||
TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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 | | |||
+----------+------------+------------+------+ | |||
要按年龄而不是按名称对输出进行排序,只需使用不同的ORDER BY子句: | |||
mysql> SELECT name, birth, CURDATE(), | |||
TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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值的动物,计算死亡和出生值之间的差异: | |||
mysql> SELECT name, birth, death, | |||
TIMESTAMPDIFF(YEAR,birth,death) 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是一个特殊值,不能使用通常的比较运算符进行比较。这将在后面讨论。 | |||
如果您想知道哪些动物下个月过生日怎么办?对于这种计算,年份和日期都不重要;您只需提取birth列的月份部分即可。MySQL提供了几个用于提取日期部分的函数,例如YEAR()、MONTH()和DAYOFMONTH()。这里适用MONTH()函数。要查看它的工作原理,请运行一个简单的查询,显示birth和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 | | |||
+----------+------------+--------------+ | |||
查找即将到来的一个月生日的动物也很简单。假设当前月份为四月。那么月份值为4,你可以这样查找出出生在五月(月份为5)的动物: | |||
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; | |||
+-------+------------+ | |||
| name | birth | | |||
+-------+------------+ | |||
| Buffy | 1989-05-13 | | |||
+-------+------------+ | |||
如果当前月份是十二月,会有一点小复杂。你不能简单地将月份数字(12)加一,然后查找出生在第13个月的动物,因为没有这样的月份。相反,你可以查找出生在一月份(月份为1)的动物。 | |||
你可以编写查询,使其无论当前月份是什么,都能正常工作,这样你就不必使用特定月份的数字。DATE_ADD()函数允许你在给定日期上添加一个时间间隔。如果你在CURDATE()的值上添加一个月份,然后使用MONTH()提取月份部分,结果就会得到要查找生日的月份: | |||
mysql> SELECT name, birth FROM pet | |||
WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH)); | |||
实现相同任务的另一种方法是在使用模数函数(MOD)将月份值包装为0(如果当前为12)之后,加1来获取当前月份之后的下一个月份: | |||
mysql> SELECT name, birth FROM pet | |||
WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1; | |||
MONTH()函数返回1到12之间的数字。而MOD(something,12)返回0到11之间的数字。所以加法必须在MOD()之后,否则我们会从11月(11)到1月(1)。 | |||
如果计算使用无效的日期,计算将失败并产生警告: | |||
mysql> SELECT '2018-10-31' + INTERVAL 1 DAY; | |||
+-------------------------------+ | |||
| '2018-10-31' + INTERVAL 1 DAY | | |||
+-------------------------------+ | |||
| 2018-11-01 | | |||
+-------------------------------+ | |||
mysql> SELECT '2018-10-32' + INTERVAL 1 DAY; | |||
+-------------------------------+ | |||
| '2018-10-32' + INTERVAL 1 DAY | | |||
+-------------------------------+ | |||
| NULL | | |||
+-------------------------------+ | |||
mysql> SHOW WARNINGS; | |||
+---------+------+----------------------------------------+ | |||
| Level | Code | Message | | |||
+---------+------+----------------------------------------+ | |||
| Warning | 1292 | Incorrect datetime value: '2018-10-32' | | |||
+---------+------+----------------------------------------+ |
2023年7月3日 (一) 17:15的版本
SELECT 语句用于从表格中提取信息。语句的一般形式如下:
SELECT 要选择的内容 FROM 哪个表格 WHERE 满足的条件;
要选择的内容指示您想要查看什么。这可以是列的列表,或者 * 表示“所有列”。哪个表格指示您要从中检索数据的表格。WHERE 子句是可选的。如果存在,满足的条件指定一个或多个行必须满足的条件才能符合检索要求。
选择所有数据
SELECT的最简单形式从表中检索所有内容:
mysql> SELECT * FROM pet; +----------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+--------+---------+------+------------+------------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Fang | Benny | dog | m | 1990-08-27 | NULL | | Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 | | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+--------+---------+------+------------+------------+
这种SELECT形式使用*,它是“选择所有列”的速记符号。如果您想查看整个表格,例如在刚刚加载初始数据集之后,这非常有用。例如,您可能会发现Bowser的出生日期似乎不太正确。查阅您的原始家谱文件后,您发现正确的出生年份应为1989年,而不是1979年。
有至少两种方法可以解决这个问题:
编辑pet.txt文件以更正错误,然后使用DELETE和LOAD DATA清空表格并重新加载它:
mysql> DELETE FROM pet; mysql> LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE pet;
但是,如果这样做,您还必须重新输入Puffball的记录。
仅使用UPDATE语句更正错误的记录:
mysql> UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser'; UPDATE仅更改有问题的记录,无需重新加载表格。
有一个例外原则,即SELECT 选择所有列。如果表中包含不可见列,则不包括它们。
选择特定的行
如前一节所示,检索整个表很容易,只需从SELECT语句中省略WHERE子句即可。但通常你不想看到整个表,特别是当它变得很大时。相反,你通常更感兴趣的是回答一个特定的问题,在这种情况下,你需要指定一些约束条件来获取所需的信息。让我们看看一些关于你的宠物的问题所回答的选择查询。
你可以只从你的表中选择特定的行。例如,如果你想验证你对Bowser的出生日期所做的更改,可以像这样选择Bowser的记录:
mysql> SELECT * FROM pet WHERE name = 'Bowser'; +--------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+-------+---------+------+------------+------------+ | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+-------+---------+------+------------+------------+
输出确认年份被正确记录为1989,而不是1979。
字符串比较通常是不区分大小写的,所以你可以将名字指定为'bowser'、'BOWSER'等等。查询结果是相同的。
你可以在任何列上指定条件,而不仅仅是名字。例如,如果你想知道哪些动物是在1998年或之后出生的,就测试出生列:
mysql> SELECT * FROM pet WHERE birth >= '1998-1-1'; +----------+-------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+-------+ | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+-------+---------+------+------------+-------+
你可以结合条件,例如找到雌性狗:
mysql> SELECT * FROM pet WHERE species = 'dog' AND sex = 'f'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
上述查询使用了AND逻辑运算符。还有一个OR运算符:
mysql> SELECT * FROM pet WHERE species = 'snake' OR species = 'bird'; +----------+-------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+-------+ | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | +----------+-------+---------+------+------------+-------+
AND和OR可以混合使用,尽管AND的优先级高于OR。如果同时使用两个运算符,最好使用括号明确指示条件应该如何分组:
mysql> SELECT * FROM pet WHERE (species = 'cat' AND sex = 'm') OR (species = 'dog' AND sex = 'f'); +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
选择特定的列
如果您不想看到表中的整行数据,只需用逗号分隔所需的列名即可。例如,如果您想知道您的动物是何时出生的,请选择名称和出生列:
mysql> SELECT name, birth FROM pet; +----------+------------+ | name | birth | +----------+------------+ | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Buffy | 1989-05-13 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Puffball | 1999-03-30 | +----------+------------+
要找出谁拥有宠物,请使用此查询:
mysql> SELECT owner FROM pet; +--------+ | owner | +--------+ | Harold | | Gwen | | Harold | | Benny | | Diane | | Gwen | | Gwen | | Benny | | Diane | +--------+
请注意,查询仅从每个记录中检索所有者列,并且其中一些列出现了多次。通过添加关键字DISTINCT,检索每个唯一的输出记录以最小化输出:
mysql> SELECT DISTINCT owner FROM pet; +--------+ | owner | +--------+ | Benny | | Diane | | Gwen | | Harold | +--------+
您可以使用WHERE子句将行选择与列选择相结合。例如,要仅获取狗和猫的出生日期,请使用此查询:
mysql> SELECT name, species, birth FROM pet WHERE species = 'dog' OR species = 'cat'; +--------+---------+------------+ | name | species | birth | +--------+---------+------------+ | Fluffy | cat | 1993-02-04 | | Claws | cat | 1994-03-17 | | Buffy | dog | 1989-05-13 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | +--------+---------+------------+
对行排序
你可能已经注意到在前面的例子中,结果行的显示顺序是没有特定顺序的。当行按某种有意义的方式排序时,检查查询结果更容易。要对结果进行排序,使用ORDER BY子句。
下面是按日期排序的动物生日:
mysql> SELECT name, birth FROM pet ORDER BY birth; +----------+------------+ | name | birth | +----------+------------+ | Buffy | 1989-05-13 | | Bowser | 1989-08-31 | | Fang | 1990-08-27 | | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Slim | 1996-04-29 | | Whistler | 1997-12-09 | | Chirpy | 1998-09-11 | | Puffball | 1999-03-30 | +----------+------------+
在字符类型的列上,排序(就像所有其他比较操作一样)通常以不区分大小写的方式进行。这意味着对于除了大小写不同的列,排序是未定义的。您可以通过使用BINARY来强制对列进行区分大小写排序,如下所示:ORDER BY BINARY col_name。
默认的排序顺序是升序,最小值排在前面。要按相反(降序)顺序排序,请在要排序的列的名称后面添加DESC关键字:
mysql> SELECT name, birth FROM pet ORDER BY birth DESC; +----------+------------+ | name | birth | +----------+------------+ | Puffball | 1999-03-30 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Claws | 1994-03-17 | | Fluffy | 1993-02-04 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Buffy | 1989-05-13 | +----------+------------+
您可以按多个列进行排序,还可以按不同的方向排序不同的列。例如,要按动物类型升序排序,然后按动物类型内的出生日期降序排序(最年轻的动物排在前面),使用以下查询:
mysql> SELECT name, species, birth FROM pet ORDER BY species, birth DESC; +----------+---------+------------+ | name | species | birth | +----------+---------+------------+ | Chirpy | bird | 1998-09-11 | | Whistler | bird | 1997-12-09 | | Claws | cat | 1994-03-17 | | Fluffy | cat | 1993-02-04 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | | Buffy | dog | 1989-05-13 | | Puffball | hamster | 1999-03-30 | | Slim | snake | 1996-04-29 | +----------+---------+------------+
DESC关键字仅适用于紧随其后的列名(birth),它不影响species列的排序顺序。
日期计算
MySQL提供了几个函数,可用于对日期进行计算,例如计算年龄或提取日期的部分。
要确定每只宠物的年龄,可以使用TIMESTAMPDIFF()函数。它的参数是要表示结果的单位,以及要计算差异的两个日期。以下查询显示了每只宠物的出生日期、当前日期和年龄(以年为单位)。使用别名(age)使最终输出列的标签更有意义。
mysql> SELECT name, birth, CURDATE(), TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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 | +----------+------------+------------+------+
该查询可以工作,但如果按某种顺序呈现行,则结果可以更容易地扫描。可以通过添加ORDER BY name子句来按名称对输出进行排序:
mysql> SELECT name, birth, CURDATE(), TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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 | +----------+------------+------------+------+
要按年龄而不是按名称对输出进行排序,只需使用不同的ORDER BY子句:
mysql> SELECT name, birth, CURDATE(), TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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值的动物,计算死亡和出生值之间的差异:
mysql> SELECT name, birth, death, TIMESTAMPDIFF(YEAR,birth,death) 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是一个特殊值,不能使用通常的比较运算符进行比较。这将在后面讨论。
如果您想知道哪些动物下个月过生日怎么办?对于这种计算,年份和日期都不重要;您只需提取birth列的月份部分即可。MySQL提供了几个用于提取日期部分的函数,例如YEAR()、MONTH()和DAYOFMONTH()。这里适用MONTH()函数。要查看它的工作原理,请运行一个简单的查询,显示birth和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 | +----------+------------+--------------+
查找即将到来的一个月生日的动物也很简单。假设当前月份为四月。那么月份值为4,你可以这样查找出出生在五月(月份为5)的动物:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+ | name | birth | +-------+------------+ | Buffy | 1989-05-13 | +-------+------------+
如果当前月份是十二月,会有一点小复杂。你不能简单地将月份数字(12)加一,然后查找出生在第13个月的动物,因为没有这样的月份。相反,你可以查找出生在一月份(月份为1)的动物。
你可以编写查询,使其无论当前月份是什么,都能正常工作,这样你就不必使用特定月份的数字。DATE_ADD()函数允许你在给定日期上添加一个时间间隔。如果你在CURDATE()的值上添加一个月份,然后使用MONTH()提取月份部分,结果就会得到要查找生日的月份:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
实现相同任务的另一种方法是在使用模数函数(MOD)将月份值包装为0(如果当前为12)之后,加1来获取当前月份之后的下一个月份:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
MONTH()函数返回1到12之间的数字。而MOD(something,12)返回0到11之间的数字。所以加法必须在MOD()之后,否则我们会从11月(11)到1月(1)。
如果计算使用无效的日期,计算将失败并产生警告:
mysql> SELECT '2018-10-31' + INTERVAL 1 DAY; +-------------------------------+ | '2018-10-31' + INTERVAL 1 DAY | +-------------------------------+ | 2018-11-01 | +-------------------------------+ mysql> SELECT '2018-10-32' + INTERVAL 1 DAY; +-------------------------------+ | '2018-10-32' + INTERVAL 1 DAY | +-------------------------------+ | NULL | +-------------------------------+ mysql> SHOW WARNINGS; +---------+------+----------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------+ | Warning | 1292 | Incorrect datetime value: '2018-10-32' | +---------+------+----------------------------------------+