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

简介:
生日问题是个看似简单逻辑上却又比较复杂的小问题
 
主要的逻辑难点第一个是关于闰月尾天的计算,第二个是判断本年度生日是否已过
 
本文给出了三种解决办法,
第一种是最常用的解决办法,即常用的 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 ,如需转载请自行联系原作者
相关文章
|
XML Android开发 数据格式
android平滑动画效果--搜索框
android平滑动画效果--搜索框
537 0
android平滑动画效果--搜索框
|
Shell 网络安全 数据安全/隐私保护
|
自然语言处理 监控 JavaScript
阿里云云开发平台x天猫精灵:打造天猫精灵个人助理Skill
各大厂商都在推自己的 Serverless 方案,今天通过一个天猫精灵技能开发来试水一下阿里云的云开发平台,整个流程走下来,不是很复杂,给我的感觉是通过阿里云开发平台开发天猫精灵技能,减轻了开发者部署后端和配置后端的环境,整个过程流畅,甚至不需要 IDE,通过浏览器就可以完成,极大降低了上手难度,是不是很神奇。
4539 0
阿里云云开发平台x天猫精灵:打造天猫精灵个人助理Skill
|
JSON Java 数据格式
统一收单交易创建接口集成开发者指南
说明: 交易创建接口主要是用于创建交易生成trade_no,配合jsapi唤起收银台来唤起支付的。 一、官方文档 官方文档地址:[url]https://docs.open.alipay.com/api_1/alipay.
1796 0
|
网络协议 数据库 数据安全/隐私保护
路由与交换利用ENSP模拟器分析和配置中小型企业网络的综合实验(中)
路由与交换利用ENSP模拟器分析和配置中小型企业网络的综合实验
4325 1
路由与交换利用ENSP模拟器分析和配置中小型企业网络的综合实验(中)
|
存储 弹性计算 分布式计算
阿里云服务器租赁费用(2022新版租赁费用及活动报价更新)
阿里云服务器租赁费用来了,本文更新了2022阿里云服务器租赁费用,包括特惠活动云服务器优惠价格及官方定价,云服务器1核2G1M带宽配置24.78元3个月1年356.83元、共享型2核4G服务器最低仅需413.86元1年、4核8G服务器765.94元1年、8核16G服务器1472.26元1年,独享型2核4G服务器最低仅需466.22元1年、4核8G服务器856.94元1年、8核16G服务器1635.74元1年。更多阿里云服务器热门配置活动报价及云服务器租赁费用及活动报价见下文。
3240 0
阿里云服务器租赁费用(2022新版租赁费用及活动报价更新)
|
存储 机器学习/深度学习 人工智能
新突破!存算一体芯片,来了
分享一个好消息——达摩院成功研发存算一体芯片!
2081 1
新突破!存算一体芯片,来了
|
图形学 异构计算
Unity【LOD Group】- 关于性能优化中LOD的使用与总结
Unity【LOD Group】- 关于性能优化中LOD的使用与总结
1354 0
Unity【LOD Group】- 关于性能优化中LOD的使用与总结
|
存储 数据挖掘 BI
数据仓库系列(四)数仓架构以及多维数据模型的设计2
数据仓库系列(四)数仓架构以及多维数据模型的设计2
790 0
数据仓库系列(四)数仓架构以及多维数据模型的设计2
|
算法 Java 测试技术
记事本中的查找是如何实现的呢?一起来看一下字符串匹配算法
你们了解字符串匹配算法吗?在我们刷算法题的时候,总有一类问题是解决字符串匹配的,其实字符串匹配是有算法技巧的,最基本的BF算法,进阶的RK算法,Sunday 算法,BM算法,KMP算法,下面我们就来一起走进这些算法。
553 0