[MySQL]-->查询5天之内过生日的同事中的闰年2月29日问题的解决过程
前言:
上次写了查询5天之内过生日的同事中的跨年问题的解决过程,网址为:http://blog.csdn.net/mchdba/article/details/38952033 ,当中漏了一个闰年2月29日生日的细节问题,如今补充一下这个问题的处理过程:
5,补充闰年推断
有朋友提醒,闰年2月29日生日的话,可能查询不到,想到确实没有考虑到这个特殊的日期。
5.1,准备測试数据SQL,包括1980-02-29这一天生日的朋友。
INSERT INTO ali_users  SELECT 'Jeff','1980-02-29','13998786549' 
UNION ALL SELECT 'WeiYa','1980-02-28','13998786549' 
UNION ALL SELECT 'XiaoTeng','1980-03-01','13998786549' 
UNION ALL SELECT 'HeSheng','1980-03-02','13998786549'
UNION ALL SELECT 'JingPan','1980-03-03','13998786549'
UNION ALL SELECT 'WuHong','1986-03-04','13998786549';
5.2,录入測试数据
- mysql> use test;
 - Reading table information for completion of table and column names
 - You can turn off this feature to get a quicker startup with -A
 - Database changed
 - mysql> INSERT INTO ali_users SELECT \'Jeff\',\'1980-02-29\',\'13998786549\' UNION ALL SELECT \'XiaoTeng\',\'1980-03-01\',\'13998786549\'
 - -> UNION ALL SELECT \'HeSheng\',\'1980-03-02\',\'13998786549\'
 - -> UNION ALL SELECT \'JingPan\',\'1980-03-03\',\'13998786549\'
 - -> UNION ALL SELECT \'WuHong\',\'1986-03-04\',\'13998786549\';
 - Query OK, 5 rows affected (0.00 sec)
 - Records: 5 Duplicates: 0 Warnings: 0
 - mysql>
 
5.3,运行原来的旧版本号的SQL查询检查结果
把Step#2中的SQL的NOW()改成'2014-02-28 00:10:10'来进行測试,确实没有包括2月29日生日的同事,例如以下所看到的:
- mysql> SELECT * FROM ali_users WHERE
 - -> DATEDIFF(CAST(CONCAT(YEAR(\'2014-02-28 00:10:10\'),DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(\'2014-02-28 00:10:10\',\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - -> OR/* or后面的是捎带解决跨年问题*/
 - -> DATEDIFF(CAST(CONCAT(YEAR(\'2014-02-28 00:10:10\')+1,DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(\'2014-02-28 00:10:10\',\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - -> ;
 - +----------+------------+-------------+
 - | username | birthday | iphone |
 - +----------+------------+-------------+
 - | XiaoTeng | 1980-03-01 | 13998786549 |
 - | HeSheng | 1980-03-02 | 13998786549 |
 - | JingPan | 1980-03-03 | 13998786549 |
 - | WuHong | 1986-03-04 | 13998786549 |
 - +----------+------------+-------------+
 - 4 rows in set, 2 warnings (0.00 sec)
 - mysql>
 
5.4,先建立一个存储函数f_isleap_year推断当年年份是否是闰年
5.4.1 准备推断是否闰年的SQL
- DELIMITER $$
 - USE `test`$$
 - DROP FUNCTION IF EXISTS `f_not_leap_year`$$
 - CREATE FUNCTION `f_not_leap_year`(p_year BIGINT) RETURNS BOOLEAN
 - BEGIN
 - /*是闰年则返回0(false),不是闰年则返回1(true)*/
 - DECLARE v_flag INT DEFAULT 0;
 - /*①、普通年能被4整除且不能被100整除的为闰年。(如2004年就是闰年,1901年不是闰年)*/
 - IF (p_year%4)=0 AND (p_year%100)>0 THEN
 - SET v_flag=0;
 - /*②、世纪年能被400整除的是闰年。(如2000年是闰年,1900年不是闰年) */
 - ELSEIF (p_year%400)=0 THEN
 - SET v_flag=0;
 - /*③、对于数值非常大的年份,这年假设能整除3200,而且能整除172800则是闰年。如172800年是闰年,
 - 86400年不是闰年(由于尽管能整除3200,但不能整除172800)(此按一回归年365天5h48\'45.5\'\'计算)。
 - */
 - ELSEIF (p_year%3200)=0 AND (p_year%172800)=0 THEN
 - SET v_flag=0;
 - ELSE
 - SET v_flag=1;
 - END IF;
 - RETURN v_flag;
 - END$$
 - DELIMITER ;
 
存储函数运行例如以下图所看到的:
 
5.4.2 准备SQL语句
- SELECT * FROM ali_users WHERE
 - DATEDIFF(CAST(CONCAT(YEAR(NOW()),DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(NOW(),\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - OR/* or后面的是捎带解决跨年问题*/
 - DATEDIFF(CAST(CONCAT(YEAR(NOW())+1,DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(NOW(),\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - OR /*补充闰年2月29日的生日问题*/
 - (
 - f_not_leap_year(YEAR(NOW()))
 - AND DATE_FORMAT(birthday,\'-%m-%d\')=\'-02-29\'
 - AND DATEDIFF(CAST(CONCAT(\'2000\',DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(CONCAT(\'2000\',DATE_FORMAT(NOW(),\'-%m-%d\')) AS DATE))
 - BETWEEN 0 AND 4
 - );
 
5.4.3 在非闰年的时候,验证闰年2月29日生日,选择2014年非闰年測试
把Step#2中的SQL的NOW()改成'2014-02-28 00:10:10'来进行測试,SQL例如以下所看到的:
SELECT * FROM ali_users WHERE 
DATEDIFF(CAST(CONCAT(YEAR('2014-02-28 00:10:10'),DATE_FORMAT(birthday,'-%m-%d'))AS DATE),CAST(DATE_FORMAT('2014-02-28 00:10:10','%y-%m-%d') AS DATE)) BETWEEN 0 AND 4
OR/* or后面的是捎带解决跨年问题*/ 
DATEDIFF(CAST(CONCAT(YEAR('2014-02-28 00:10:10')+1,DATE_FORMAT(birthday,'-%m-%d'))AS DATE),CAST(DATE_FORMAT('2014-02-28 00:10:10','%y-%m-%d') AS DATE)) BETWEEN 0 AND 4
OR /*补充闰年2月29日的生日方法*/
(
f_not_leap_year(YEAR('2014-02-28 00:10:10')) 
AND DATE_FORMAT(birthday,'-%m-%d')='-02-29' 
AND DATEDIFF(CAST(CONCAT('2000',DATE_FORMAT(birthday,'-%m-%d'))AS DATE),CAST(CONCAT('2000',DATE_FORMAT('2000-02-28 00:10:10','-%m-%d')) AS DATE)) 
BETWEEN 0 AND 4
);
运行SQL检验成果,假设当天是2014-02-28,看到已经有2月29日的生日的同事被记录进来了,事实上包括了2月28日、2月29日、3月1日、3月2日、3月3日、3月4日的生日的同事。
PS:由于2月29日在当年不存在,所以不算这5天之内的范畴,运行结果例如以下所看到的:
- mysql> SELECT * FROM ali_users WHERE
 - -> DATEDIFF(CAST(CONCAT(YEAR(\'2014-02-28 00:10:10\'),DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(\'2014-02-28 00:10:10\',\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - -> OR/* or后面的是捎带解决跨年问题*/
 - -> DATEDIFF(CAST(CONCAT(YEAR(\'2014-02-28 00:10:10\')+1,DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(\'2014-02-28 00:10:10\',\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - -> OR /*补充闰年2月29日的生日方法*/
 - -> (
 - -> f_not_leap_year(YEAR(\'2014-02-28 00:10:10\'))
 - -> AND DATE_FORMAT(birthday,\'-%m-%d\')=\'-02-29\'
 - -> AND DATEDIFF(CAST(CONCAT(\'2000\',DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(CONCAT(\'2000\',DATE_FORMAT(\'2000-02-28 00:10:10\',\'-%m-%d\')) AS DATE))
 - -> BETWEEN 0 AND 4
 - -> );
 - +----------+------------+-------------+
 - | username | birthday | iphone |
 - +----------+------------+-------------+
 - | Jeff | 1980-02-29 | 13998786549 |
 - | XiaoTeng | 1980-03-01 | 13998786549 |
 - | HeSheng | 1980-03-02 | 13998786549 |
 - | JingPan | 1980-03-03 | 13998786549 |
 - | WuHong | 1986-03-04 | 13998786549 |
 - | WeiYa | 1980-02-28 | 13998786549 |
 - +----------+------------+-------------+
 - 6 rows in set, 2 warnings (0.00 sec)
 - mysql>
 
5.4.4 在闰年的时候,验证闰年2月29日生日,选择2004年闰年測试
把Step#2中的SQL的NOW()改成'2004-02-28 00:10:10'来进行測试,SQL例如以下所看到的:
- SELECT * FROM ali_users WHERE
 - DATEDIFF(CAST(CONCAT(YEAR(\'2004-02-28 00:10:10\'),DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(\'2004-02-28 00:10:10\',\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - OR/* or后面的是捎带解决跨年问题*/
 - DATEDIFF(CAST(CONCAT(YEAR(\'2004-02-28 00:10:10\')+1,DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(\'2004-02-28 00:10:10\',\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - OR /*补充闰年2月29日的生日方法*/
 - (
 - f_not_leap_year(YEAR(\'2004-02-28 00:10:10\'))
 - AND DATE_FORMAT(birthday,\'-%m-%d\')=\'-02-29\'
 - AND DATEDIFF(CAST(CONCAT(\'2000\',DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(CONCAT(\'2000\',DATE_FORMAT(\'2004-02-28 00:10:10\',\'-%m-%d\')) ASDATE))
 - BETWEEN 0 AND 4
 - );
 
运行SQL检验成果,假设当天是2004-02-28,看到已经有2月29日的生日的同事被记录进来了,事实上包括了2月28日、2月29日、3月1日、3月2日、3月3日的生日的同事。
PS:由于2月29日在当年存在,所以算这5天之内的范畴,运行结果例如以下所看到的:
- mysql> SELECT * FROM ali_users WHERE
 - -> DATEDIFF(CAST(CONCAT(YEAR(\'2004-02-28 00:10:10\'),DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(\'2004-02-28 00:10:10\',\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - -> OR/* or后面的是捎带解决跨年问题*/
 - -> DATEDIFF(CAST(CONCAT(YEAR(\'2004-02-28 00:10:10\')+1,DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(DATE_FORMAT(\'2004-02-28 00:10:10\',\'%y-%m-%d\') AS DATE)) BETWEEN 0 AND 4
 - -> OR /*补充闰年2月29日的生日方法*/
 - -> (
 - -> f_not_leap_year(YEAR(\'2004-02-28 00:10:10\'))
 - -> AND DATE_FORMAT(birthday,\'-%m-%d\')=\'-02-29\'
 - -> AND DATEDIFF(CAST(CONCAT(\'2000\',DATE_FORMAT(birthday,\'-%m-%d\'))AS DATE),CAST(CONCAT(\'2000\',DATE_FORMAT(\'2004-02-28 00:10:10\',\'-%m-%d\')) AS DATE))
 - -> BETWEEN 0 AND 4
 - -> );
 - +----------+------------+-------------+
 - | username | birthday | iphone |
 - +----------+------------+-------------+
 - | Jeff | 1980-02-29 | 13998786549 |
 - | XiaoTeng | 1980-03-01 | 13998786549 |
 - | HeSheng | 1980-03-02 | 13998786549 |
 - | JingPan | 1980-03-03 | 13998786549 |
 - | WeiYa | 1980-02-28 | 13998786549 |
 - +----------+------------+-------------+
 - 5 rows in set (0.00 sec)
 - mysql>
 
[MySQL]-->查询5天之内过生日的同事中的闰年2月29日问题的解决过程的更多相关文章
- mysql如何查询一个字段在哪几张表中
		
SELECT TABLE_SCHEMA,TABLE_NAME FROM information_schema.`COLUMNS` WHERE COLUMN_NAME = 'xxx' ; xxx替换成需 ...
 - 2017年10月29日   数据库查询总结&45道题
		
日期函数: 当前时间:GetDate() 两个时间差:DateDiff() 一. 设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Tea ...
 - mysql慢查询和php-fpm慢日志
		
MySQL慢查询 在web开发中,我们经常会写出一些SQL语句,一条糟糕的SQL语句可能让你的整个程序都非常慢,超过10秒一般用户就会选择关闭网页,如何优化SQL语句将那些运行时间 比较长的SQL语句 ...
 - mysql去重, 把url重复且区为空的中去掉、统计重复数据、、结果集去重合并成一行
		
delete from 表名 where id not in (select d.id from (SELECT id FROM 表名 GROUP BY c1,c2,c3,c4)as d) #去重复, ...
 - 下厨房6月26日数据丢失事故总结 MYSQL主分区被rm 命令误删除
		
下厨房6月26日数据丢失事故总结 MYSQL主分区被rm 命令误删除 http://tech.xiachufang.com/?p=18 在6月26日凌晨12点左右,我们在做线上数据库的备库时,误将线上 ...
 - hdu 1201:18岁生日(水题,闰年)
		
18岁生日 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
 - MySQL 慢查询配置
		
MYSQL慢查询 1. 慢查询有什么用? 它能记录下所有执行超过long_query_time时间的SQL语句, 帮你找到执行慢的SQL, 方便我们对这些SQL进行优化. 2. 如何开启慢查询? 首先 ...
 - MySQL联接查询算法(NLJ、BNL、BKA、HashJoin)
		
一.联接过程介绍 为了后面一些测试案例,我们事先创建了两张表,表数据如下: 1 2 3 4 CREATE TABLE t1 (m1 int, n1 char(1)); CREATE TABLE t ...
 - mysql慢查询配置
		
1.慢查询有什么用? 能记录下所有执行超过long_query_time时间的SQL语句, 帮你找到执行慢的SQL, 方便我们对这些SQL进行优化. 2. 如何开启慢查询? 首先我们先查看MYSQL服 ...
 
随机推荐
- hdu 4296 Buildings(贪婪)
			
主题链接:http://acm.hdu.edu.cn/showproblem.php? pid=4296 Buildings Time Limit: 5000/2000 MS (Java/Others ...
 - JAVA card 应用程序开发(七) JAVA 卡数据(永久数据/)时间数据
			
JAVA 卡对象 JAVA CARD 存储器装置: a. ROM: 永久保存程序和数据,虚拟机,API等待:(Applets它也可以在这里放) b. RAM: 栈数据,暂时对象. ...
 - NVIDIA+关联2015写学校招收评论(嵌入式方向,上海)
			
我没有写很长一段时间Blog中的一个,在过去的几个月中还没有看到太多的生长技术,来来回回一直在做的事情,要毕业找工作,但发现并没有冷静下来,准备过.这不是让人觉得暂时补习班是凡人啊. 本科不试试.那你 ...
 - 思维导图之C++语言程序设计总结
			
花了大约一周的时间,将c++的课本过了一遍,米老师说第一遍不求甚解,仅仅管去看就能够了,我很成功地运行了老师这种方法,嘿嘿.那么c++是什么呢?百度上这样说,它是一种使用很广泛的计算机编程语言.C++ ...
 - etl工具,kettle实现了周期
			
Kettle这是国外的来源ETL工具,纯java写.能Window.Linux.Unix在执行.绿色无需安装,稳定高效的数据提取. 业务模型: 在关系型数据库中有张非常大的数据存储表,被设计成奇偶库存 ...
 - 微通道产品经理Grover采访:美国的微通道设计
			
"'哥'在中国是一种尊称吗?哈哈.我们平时都叫张小龙'龙哥'." "是的.Dan哥,当你认为某个人牛逼的时候,你就能够叫他'哥'." 我对于Dan Grover ...
 - Html5 拖放上传图片
			
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...
 - 【翻译】Ext JS最新技巧——2014-10-30
			
原文:Top Support Tips Greg Barry:Ext JS 5的ExtraParams Ext JS 4同意用户直接将extraParams加入到一个链接,相似例如以下代码: Ext. ...
 - Team Foundation Server 2015使用教程--团队项目删除
 - C++ 内部排序(一)
			
先讲两个概念,所谓内部排序,指待排序的节点均存储在内存中.所谓排序的稳定性,指排序后,值相等的两个元素原来相对的位置是否发生变化了.举个例子. 待排序列:3(1),1,5,3(2) 稳定排序:1,3 ...