热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于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

 


推荐阅读
  • Java 零基础入门:SQL Server 学习笔记(第21篇)
    Java 零基础入门:SQL Server 学习笔记(第21篇) ... [详细]
  • 本文详细介绍了MySQL数据库的基础语法与核心操作,涵盖从基础概念到具体应用的多个方面。首先,文章从基础知识入手,逐步深入到创建和修改数据表的操作。接着,详细讲解了如何进行数据的插入、更新与删除。在查询部分,不仅介绍了DISTINCT和LIMIT的使用方法,还探讨了排序、过滤和通配符的应用。此外,文章还涵盖了计算字段以及多种函数的使用,包括文本处理、日期和时间处理及数值处理等。通过这些内容,读者可以全面掌握MySQL数据库的核心操作技巧。 ... [详细]
  • MySQL初级篇——字符串、日期时间、流程控制函数的相关应用
    文章目录:1.字符串函数2.日期时间函数2.1获取日期时间2.2日期与时间戳的转换2.3获取年月日、时分秒、星期数、天数等函数2.4时间和秒钟的转换2. ... [详细]
  • SQL 语句的性能优化:你做到了吗?
    在 SQL Server 查询性能优化中,书签查找的作用不容忽视。本文深入探讨了书签查找对查询效率的影响,并提供了实用的优化策略,帮助开发者提升数据库性能。通过具体案例分析,文章展示了如何有效避免不必要的书签查找,从而显著提高查询速度和系统响应时间。 ... [详细]
  • 本文讨论了在 Oracle 10gR2 和 Solaris 10 64-bit 环境下,从 XMLType 列中提取数据并插入到 VARCHAR2 列时遇到的性能问题,并提供了优化建议。 ... [详细]
  • 包含phppdoerrorcode的词条 ... [详细]
  • 一个建表一个执行crud操作建表代码importandroid.content.Context;importandroid.database.sqlite.SQLiteDat ... [详细]
  • importpymysql#一、直接连接mysql数据库'''coonpymysql.connect(host'192.168.*.*',u ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • MySQL 数据操作:增、删、查、改全面解析
    MySQL 数据操作:增、删、查、改全面解析 ... [详细]
  • 提升MySQL数据库架构性能的策略与方法
    为了提升MySQL数据库架构的性能,本文探讨了多种策略与方法。首先,分析了影响数据库性能的关键因素,并详细阐述了数据库结构优化的重要性。接着,介绍了数据库设计的基本步骤,包括第一、第二和第三范式的应用,以及反范式化设计的场景。此外,还讨论了数据库物理设计的关键要素,如表定义、索引设计和存储引擎选择,以确保高效的查询响应和数据管理。 ... [详细]
  • 定制数据层关键字:数据层,访问,元数据,数据访问模型http://www.gaodaima.com/35448.html定制数据层_sqlserver ... [详细]
  • 假设我有一张源表customer_account中有一个字段crm_id_content,字段的内容大概为这种模式<r><uid{F7898717-4954-E123 ... [详细]
  • 这篇文章主要讲解了“SQLServer与Access数据库ASP代码有什么区别”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深 ... [详细]
  • sqldouble222.22222222如何转换成字符串222.22222222%convertcast都是保留4位小数。 ... [详细]
author-avatar
手机用户2602919763
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有