生日问题是个看似简单逻辑上却又比较复杂的小问题
主要的逻辑难点第一个是关于闰月尾天的计算,第二个是判断本年度生日是否已过
本文给出了三种解决办法,
第一种是最常用的解决办法,即常用的 SQL 语法,不过看起来比较复杂,适合环境为 SQLServer2000 以上
第二种是采用函数的方法,把对日期的逻辑处理放到函数中,调用起来会简约一下,适合环境为 SQLServer2000 以上
第三种是采用 CTE 的方法,用 CTE 来封装判断逻辑,适合环境为 SQLServer2005 以上
-- 创建表和数据
CREATE TABLE employees
(
name     VARCHAR(50),
birthday DATETIME
)
INSERT INTO employees VALUES('WBQ','1948-12-08');
INSERT INTO employees VALUES('CZH','1952-02-19');
INSERT INTO employees VALUES('LB','1963-08-30');
INSERT INTO employees VALUES('YLL','1937-09-19');
INSERT INTO employees VALUES('YGQ','1955-03-04');
INSERT INTO employees VALUES('CHH','1963-07-02');
INSERT INTO employees VALUES('SWG','1960-05-29');
INSERT INTO employees VALUES('HW','1958-01-01');
INSERT INTO employees VALUES('YY','1972-02-29');
INSERT INTO employees VALUES('LM','1999-02-08');
INSERT INTO employees VALUES('ZY','1972-06-09');
INSERT INTO employees VALUES('WZH','1999-02-28');
SELECT name,birthday FROM employees 
 
-- 普通的 SQL 实现
SELECT
name,
birthday,
GETDATE() getdate,
CONVERT(VARCHAR(10),GETDATE(),120) todayVarchar,
CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),120)) todayDateTime,
DATEDIFF(YY,birthday,GETDATE()) DateBetween,
DATEADD(YY,DATEDIFF(YY,birthday,GETDATE()),birthday) ThisBirthday,
DATEADD(YY,DATEDIFF(YY,birthday,GETDATE())+1,birthday) NextBirthday,
CASE WHEN CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),120))>DATEADD(YY,DATEDIFF(YY,birthday,GETDATE()),birthday)
THEN DATEADD(YY,DATEDIFF(YY,birthday,GETDATE())+1,birthday)
ELSE DATEADD(YY,DATEDIFF(YY,birthday,GETDATE()),birthday)
END newBirthdayStandard,
CASE WHEN CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),120))>DATEADD(YY,DATEDIFF(YY,birthday,GETDATE()),birthday)       
THEN DATEADD(YY,DATEDIFF(YY,birthday,GETDATE())+1,birthday)+
CASE WHEN DAY(birthday)=29 AND DAY(DATEADD(YY,DATEDIFF(YY,birthday,GETDATE())+1,birthday))=28 THEN 1 ELSE 0 END
ELSE DATEADD(YY,DATEDIFF(YY,birthday,GETDATE()),birthday) +
CASE WHEN DAY(birthday)=29 AND DAY(DATEADD(YY,DATEDIFF(YY,birthday,GETDATE()),birthday))=28 THEN 1 ELSE 0 END
END newBirthdayForeign 
FROM employees 
 
-- 使用函数来实现
CREATE FUNCTION GetBirthday(@birthday DATETIME,@flag INT)
RETURNS DATETIME
AS
BEGIN
DECLARE @BirthdayRet DATETIME,@BirthdayThis DATETIME,@BirthdayNext DATETIME,@today DATETIME,@dateBetween INT
SET @today=CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),120))
SET @dateBetween=DATEDIFF(YY,@birthday,GETDATE())
SET @BirthdayThis=DATEADD(YY,@DateBetween,@birthday)    
SET @BirthdayNext=DATEADD(YY,@DateBetween+1,@birthday)
IF @flag=1 --2 月 29 日的生日计算为 2 月 28 日
BEGIN
IF @today>@BirthdayThis
SET @BirthdayRet=@BirthdayNext
ELSE
SET @BirthdayRet=@BirthdayThis
END
ELSE       --2 月 29 日的生日计算为 3 月 1 日
BEGIN
IF @today>@BirthdayThis
IF DAY(@birthday)=29 AND DAY(@BirthdayNext)=28
SET @BirthdayRet=@BirthdayNext+1
ELSE
SET @BirthdayRet=@BirthdayNext
ELSE
IF DAY(@birthday)=29 AND DAY(@BirthdayThis)=28
SET @BirthdayRet=@BirthdayThis+1
ELSE
SET @BirthdayRet=@BirthdayThis  END    
RETURN @BirthdayRet
END
SELECT name,birthday,dbo.GetBirthday(birthday,0),dbo.GetBirthday(birthday,1) FROM employees 
 
-- 通过 CTE 来实现
WITH DateBetween AS
(
SELECT  
name,
birthday,
GETDATE() getdate,
CONVERT(VARCHAR(10),GETDATE(),120) todayVarchar,
CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),120)) todayDateTime,
DATEDIFF(YY,birthday,GETDATE()) DateBetween
FROM employees
),
DateBirthdayThisAndNext AS
(
SELECT
name,birthday,getdate,todaydatetime,datebetween,
DATEADD(YY,DateBetween,birthday) AS DateCur,
DATEADD(YY,DateBetween+1,birthday) AS DateNext
FROM DateBetween
),
DateBirthdayThisAndNextForeign AS
(
SELECT
name,birthday,todaydatetime,
DateCur,DateNext,
DateCur+CASE WHEN DAY(birthday)=29 AND DAY(DateCur)=28 THEN 1 ELSE 0 END AS DateCurForeign,
DateNext+CASE WHEN DAY(birthday)=29 AND DAY(DateNext)=28 THEN 1 ELSE 0 END AS DateNextForeign
FROM DateBirthdayThisAndNext
),
DateBirthday AS
(
SELECT
name,birthday,
CASE WHEN DateCurForeign>=todaydatetime THEN DateCurForeign ELSE DateNextForeign END AS birthDayForeign,
CASE WHEN DateCur>=todaydatetime THEN DateCur ELSE DateNext END AS birthDayStandard
FROM DateBirthdayThisAndNextForeign
)
SELECT name,birthday,birthDayForeign,birthDayStandard FROM DateBirthday 
 
 
本文转自baoqiangwang51CTO博客,原文链接:http://blog.51cto.com/baoqiangwang/310453,如需转载请自行联系原作者

关于SQLServer2005的学习笔记——生日问题相关推荐

  1. 关于SQLServer2005的学习笔记——XML的处理

    在 SQLServer2005 中对 XML 的处理功能显然增强了很多,提供了 query(),value(),exist(),modify(),nodes() 等函数.关于 xml ,难以理解的不是 ...

  2. 关于SQLServer2005的学习笔记——SQL查询解析步骤

    最近一来因工作上的事情比较闹心,没心事再研究 SQLServer2005 的体系结构:一来关于体系结构确实过于复杂,远远不如应用来的直接明了,所以暂时搁笔. 出于工作上的需要,对应用开发需要更多的了解 ...

  3. 关于SQLServer2005的学习笔记——约束、Check、触发器的执行顺序

    通常我们认为一条 Insert 就是一个事务,但这个事务是如何执行的呢?如果保障事务执行时该事务的完整性和一致性呢?抛开存储机制.索引.锁等环节,让我们看看约束. Check 和触发器在这个过程中的先 ...

  4. 关于SQLServer2005的学习笔记——CTE递归和模拟测试数据

    在 Oracle 中模拟测试 数据是非常简单的一件事情. Oracle 首先提供了一个 dual 的虚表 其次提供了一个 Connect by 语句,实现了虚表数据列的模拟 最后 Oracle 提供了 ...

  5. B站《一天学会 MySQL 数据库》学习笔记

    B站<一天学会 MySQL 数据库>学习笔记 老司机带我飞 职场十字诀:思考.计划.行动.总结.反思 ​关注他 4 人赞同了该文章 登录和退出MySQL服务器 # 登录MySQL $ my ...

  6. mybatis学习笔记(3)-入门程序一

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(3)-入门程序一 标签: mybatis [TOC] 工程结构 在IDEA中新建了一个普通的java项 ...

  7. HTML/CSS学习笔记02【表单标签】

    w3cschool菜鸟教程.CHM(腾讯微云):https://share.weiyun.com/c1FaX6ZD HTML/CSS学习笔记01[概念介绍.基本标签.表单标签][day01] HTML ...

  8. MySQL学习笔记05【多表操作、三大范式、数据库的备份和还原】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  9. Spring Boot学习笔记-基础(2)

    Spring Boot学习笔记-基础(2) Spring Boot 优点: – 快速创建独立运行的Spring项目以及与主流框架集成 – 使用嵌入式的Servlet容器,应用无需打成WAR包 – st ...

最新文章

  1. Swift - 简单的原生与网页交互
  2. [Python Machine Learning] 学习笔记之scikit-learn机器学习库
  3. LVM逻辑卷详解及创建
  4. 初探CSRF在ASP.NET Core中的处理方式
  5. 将gcc/g++链接到指定版本
  6. android textview 动态高度自适应,TextView自适应高度(解决_UITextContainerView布局问题)...
  7. 经典书单 —— 计算机图形学
  8. rsync内网服务器 推送和拉取公网代码配置
  9. Smart3D输出/输入空三结果
  10. navicat 注册过程
  11. 【雕爷学编程】Arduino动手做(100)---MAX30102手腕心率
  12. 10倍性能提升!英伟达新卡皇降临,图灵架构GTX 20系列发布
  13. C语言实现线性表的链式存储结构
  14. 基于51单片机定时,数码管显示时间
  15. 【Qt Quick】设置圆形图片
  16. mkv导入Pr没有音频,mkv无法导入的解决方法
  17. 玩转AgileCDN(二)——运维小哥做报表,不再为时区换算而烦恼
  18. 前端程序员福利 利用node写接口
  19. opencv-python图片的镜像
  20. “希希敬敬对”团队--‘百度贴吧小爬虫’Alpha版本展示博客

热门文章

  1. 全局光照---光线跟踪方法
  2. ireport学习笔记
  3. LeetCode刷题(42)--Subsets
  4. import pycharm setting_Pycharm不能正常使用的常见问题
  5. html jsf ajax blur,是否可以使用JSF ajax更新非JSF组件(纯HTML)?
  6. java gc回收算法_Java基础之GC垃圾回收的历史
  7. php ci base url,CodeIgniter中base_url问题
  8. nignx解决vue部署服务器刷新页面出现404问题
  9. 全网最全的git命令大全
  10. Python 入门介绍