一道关于生日计算的简单mysql题目

一看到有关日期的简单题目,但要精确计算还是需要一些并不常用的函数。
今天做到一个简单的题目:
要求:1、查询各学生的年龄
2、字段要求及顺序:学号(s_id)、姓名(s_name)、出生日期s_birth。
其中s_birth是char(255)格式,直接用year()函数计算显然会造成不显著偏误。

1.方法1:条件函数

两种实现需求的mysql查询语句如下:

select 
    s_id
    ,s_name
    ,if(month(curdate())-month(s_birth)>0,year(curdate())-year(s_birth),year(curdate())-year(s_birth)-1) as age
from student;

当然if函数也可以用case when语法代替

select s_id
       ,s_name
       ,(case when month(s_birth) >= month(curdate()) then year(curdate())-year(s_birth)
         else year(curdate())-year(s_birth)-1 end) as age
from student;

思路比较简单:
判断如果当前日期的月份大于出生日期的月份,则直接用年份相减。如果当前日期的月份小于出生日期的月份,则用年份想减得到的差还要减1才能得到年龄。

2.方法2:向下取整

select 
    s_id
    ,s_name
    ,floor( (datediff( curdate(),date(s_birth) ) / 365) ) as age
from student;

3.方法3(最好,推荐,也最准确):时间处理函数

select s_id
       ,s_name
       ,timestampdiff(year,str_to_date(s_birth,'%Y-%m-%d'),curdate()) as as age_by_diff
from student;
#str_to_date()函数中的时间序列格式无所谓,timestampdiff()函数都可以识别并计算

此处发现一个问题,下一段代码与上一段代码的区别是使用了date_format函数而不是str_to_date函数,居然得到了一样的结果。这两个函数的数据变化方向实际是完全相反的。涉及到mysql中隐式转换的过程,这里只要知道显式转换优于隐式转换就好,原理个人研究后认为并不能从底层理解,无法推广,只能遇到了特例查询判断就好。这里仅是巧合。

select s_id
       ,s_name
       ,timestampdiff(year,date_format(s_birth,'%Y-%m-%d'),curdate()) as as age_by_diff
from student;

总而言之,最优的方法是str_to_date()和timestampdiff()联用解决此问题,思路直接,语法也相对简单,精确度高。

涉及到的函数:

1.if()

IF(expr, if_true_expr, if_false_expr)

expr:要评估的条件表达式(返回 TRUE、FALSE 或 NULL)
if_true_expr:当 expr 为 TRUE(非零且非 NULL)时返回的值
if_false_expr:当 expr 为 FALSE 或 NULL 时返回的值

2.floor(x)
向下取整。(和ceiling()的功能恰好相反)
例如:
x=3.7,会输出3.
x=3.2,依旧会输出3

3.STR_TO_DATE() 和DATE_FORMAT()函数
STR_TO_DATE() 是 MySQL 中用于将字符串转换为日期时间值的函数,特别适用于将非标准格式的日期字符串转换为 MySQL 可识别的日期时间格式。

相反的,DATE_FORMAT()函数是将日期时间值格式化为字符串的函数。

实际应用场景
DATE_FORMAT() 典型用途:
在报表中显示格式化的日期
将日期转换为特定格式用于导出
在应用程序界面中显示用户友好的日期格式

STR_TO_DATE() 典型用途:
导入非标准格式的日期数据
处理用户输入的日期字符串
将文本文件中的日期转换为数据库可识别的格式

语法
STR_TO_DATE(str, format)
str:要转换的日期时间字符串
format:指定输入字符串的格式

DATE_FORMAT(date, format)
date:DATE、DATETIME或TIMESTAMP类型的值
format:指定输出格式的格式字符串

这里想要看一下两种函数输出的数据类型,可以用以下方法。创建一个临时表后用

create temporary table temp_table as 
(select date_format('20050312',"%Y%m%d")) limit 0;
describe temp_table;
drop temporary table temp_table;
#limit 0 表示只引入表结构而不包含数据

看到type类型显示的是varchar(8)。

create temporary table temp_table as 
(select timestamp(date_format('20050312',"%Y%m%d"))) limit 0;
describe temp_table;
drop temporary table temp_table;

看到type类型显示的是datetime。

create temporary table temp_table as 
(select str_to_date('20050312',"%Y%m%d")) limit 0;
describe temp_table;
drop temporary table temp_table;

看到type类型显示的是date。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容