我正在阅读文档中的MySql教程,并有以下表和SQL语句:
事件表:
+----------+------------+----------+------------------------------+
| name | date | type | remark |
+----------+------------+----------+------------------------------+
| Fluffy | 1995-05-15 | litter | 4 kittens, 3 females, 1 male |
| Buffy | 1993-06-23 | litter | 5 puppies, 2 female, 3 male |
| Buffy | 1994-06-19 | litter | 3 puppies, 3 female |
| Chirpy | 1999-03-21 | vet | needed beak streightened |
| Slim | 1997-08-03 | vet | broken rib |
| Bowser | 1991-10-12 | kennel | NULL |
| Fang | 1991-10-12 | kennel | NULL |
| Fang | 1998-08-28 | birthday | Gave him new chew toy |
| Claws | 1998-03-17 | birthday | Gave him a flea collar |
| Whistler | 1998-12-09 | birthday | First birthday |
+----------+------------+----------+------------------------------+
宠物表:
+----------+--------+---------+------+------------+------------+
| 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 | 1989-03-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 |
| Jenny | Robert | dog | f | 2004-01-01 | 2014-05-04 |
+----------+--------+---------+------+------------+------------+
SQL: select pet.name,
( YEAR(date) - YEAR(birth) ) - ( RIGHT(date,5) < RIGHT(birth,5) ) AS age, remark
from pet inner join event
on pet.name = event.name
where event.type = 'litter';
我理解SQL语句,除了这一条:
( YEAR(date) - YEAR(birth) ) - ( RIGHT(date,5) < RIGHT(birth,5) )
YEAR()
函数用于从日期中提取年份。
正如你所提到的,YEAR()
从日期中获取年份。
我们将使用Fluffy作为birth = 1993-02-04
和date = 1995-05-15
的示例
步骤1:从两个日期( YEAR(date) - YEAR(birth) )
中减去提取的年份现在是1995 - 1993,等于2
步骤2:( RIGHT(date,5) < RIGHT(birth,5) )
这实际上将从右到左读取日期和出生字符串5步,因此如果执行RIGHT(date,5)
,您将获得值0,如果执行RIGHT(birth,5)
,您也将获得值0。
步骤3:现在我们进入<
操作符,如果满足条件,则返回布尔值1或0。由于0 = 0,该语句为假,因此它将返回0。
整个函数实际上检查date
的日期部分是否小于birthdate
的日期,这将确定您在一整年之前是否有一些剩余的日子。如果您这样做,它将返回1,该1将从您之前执行的当前年-年运算中减去。
但是在我们的例子中,由于<
将返回0,我们可以肯定地说Fluffy的年龄是2 - 0,也就是2。
但是,如果Fluffy的birthdate
是1993-12-04,这将为<
操作产生1
值,这意味着年份尚未完成,这将导致结果2- 1,即1。
对不起,如果它有点乱。
如果你是1980年出生的,我知道现在是2015年,那么我可以几乎通过计算YEAR(date) - YEAR(birth) = 2015 - 1980 = 35
来计算你的年龄。关键是你的生日可能还没到。那我怎么知道你过生日了呢?假设你出生于1980年7月20日。然后在MySQL日期格式中,你的生日看起来像2015-06-20。如果我看你生日的最后5个字符,最右边的 5个字符,或者RIGHT(birth, 5)
,我会得到06-20。如果今天日期的最后5个字符,06-07
小于你生日的最后5个字符,那么你的生日还没有发生。这里,"小于"的意思是它将按照正常的字符串顺序"排序"。所以,如果RIGHT(date, 5) < RIGHT(birth, 5)
,那么你的生日还没有发生。而且,幸运的是,MySQL将"真"视为数字1
,将"假"视为数字0
。因此,只有当您的生日还没有发生时,上面的代码才会从日期计算中减去1
。
这是一种聪明的(?)方法来检查出生日期的月份和日期是否发生在事件(垃圾)的日期之前或之后,以便正确计算事件之间的年数(因为年部分本身是不够的)。
本部分:
( YEAR(date) - YEAR(birth) ) - ( RIGHT(date,5) < RIGHT(birth,5) )
RIGHT(date,5)
返回像(03-30
)一样的月份和日期部分,并进行布尔小于比较,根据结果返回0或1。然后从YEAR(date) - YEAR(birth)
计算中减去这个值,以便正确调整事件之间的年份。