SQL Server:Le年的生日

RoL*_*LLs 3 t-sql sql-server leap-year

我有一张有员工生日的桌子。我正在尝试创建一个存储过程,该过程将在2个给定日期内返回每个人的生日。我们的员工出生于a年。

按照http://www.berezniker.com/content/pages/sql/microsoft/sql-server/birthday-query-ms-sql-server上的示例,当他们的生日在a年时,我可以成功返回一个人

DECLARE @StartDate DATETIME, @EndDate DATETIME

SET @StartDate = '2009-02-22'
SET @EndDate   = '2009-02-28'

--SET @StartDate = '2008-02-22'
--SET @EndDate   = '2008-02-29'

SELECT 
  FullName, 
  DATEPART(MONTH, dob) AS MONTH, 
  DATEPART(DAY, dob) AS DAY, 
  CONVERT(VARCHAR(10), dob, 111) AS dob
FROM 
  People
WHERE  
  DATEADD(YEAR, DATEDIFF(YEAR,  dob, @StartDate), dob) BETWEEN @StartDate AND @EndDate
OR 
  DATEADD(YEAR, DATEDIFF(YEAR,  dob, @EndDate), dob) BETWEEN @StartDate AND @EndDate
ORDER BY 
  CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR,  dob, @StartDate), dob) 
  BETWEEN @StartDate AND @EndDate THEN 1 ELSE 2 END, 
  DATEPART(MONTH, dob), DATEPART(DAY, dob)


CREATE TABLE People 
    (
        PK INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
        FullName VARCHAR(30) NOT NULL,
        dob DATETIME NULL
    )
GO

INSERT INTO People (FullName, dob) VALUES ('John Smith', '1965-02-28')
INSERT INTO People (FullName, dob) VALUES ('Alex Black', '1960-02-29')
INSERT INTO People (FullName, dob) VALUES ('Bill Doors', '1968-02-27')
...
--shortened for clarity
Run Code Online (Sandbox Code Playgroud)

但是,使用上述数据,我的目标是将Alex Black2014年2/28/2014和2016 年的生日显示为2/29/2016。

另外,如果您有心情,请注意以下几点:

我想传递2个日期,无论相隔多远:@DateFrom date = '1/1/2014'和@DateTo date = '12/31/2016'。我要回的结果是

FULLNAME        DOB
Bill Doors      2014-02-27
John Smith      2014-02-28
Alex Black      2014-02-28
Bill Doors      2015-02-27
John Smith      2015-02-28
Alex Black      2015-02-28
Bill Doors      2016-02-27
John Smith      2016-02-28
Alex Black      2016-02-29 -- note this year the date is feb 29th
Run Code Online (Sandbox Code Playgroud)

Lam*_*mak 5

这是一种方法:

DECLARE @StartDate DATETIME, @EndDate DATETIME, @I INT

SET @StartDate = '20140101'
SET @EndDate   = '20161231'
SET @I = 0

DECLARE @Years TABLE(Years DATE)


WHILE @I <= DATEDIFF(YEAR,@StartDate,@EndDate)
BEGIN
    INSERT INTO @Years
    SELECT DATEADD(YEAR,DATEDIFF(YEAR,0,DATEADD(YEAR,@I,@StartDate)),0)

    SET @I = @I + 1
END

SELECT  B.FullName,
        B.dob,
        DATEADD(YEAR,DATEDIFF(YEAR,dob,Years),dob) BirthDay
FROM @Years A
CROSS JOIN People B
WHERE DATEADD(YEAR,DATEDIFF(YEAR,dob,Years),dob) >= @StartDate
AND DATEADD(YEAR,DATEDIFF(YEAR,dob,Years),dob) <= @EndDate
Run Code Online (Sandbox Code Playgroud)

当然,您不必@Years每次都创建该表,建议您使用此信息创建日历表。

结果:

??????????????????????????????????????????????????????????????????
?  FullName  ?           dob           ?        BirthDay         ?
??????????????????????????????????????????????????????????????????
? John Smith ? 1965-02-28 00:00:00.000 ? 2014-02-28 00:00:00.000 ?
? Alex Black ? 1960-02-29 00:00:00.000 ? 2014-02-28 00:00:00.000 ?
? Bill Doors ? 1968-02-27 00:00:00.000 ? 2014-02-27 00:00:00.000 ?
? John Smith ? 1965-02-28 00:00:00.000 ? 2015-02-28 00:00:00.000 ?
? Alex Black ? 1960-02-29 00:00:00.000 ? 2015-02-28 00:00:00.000 ?
? Bill Doors ? 1968-02-27 00:00:00.000 ? 2015-02-27 00:00:00.000 ?
? John Smith ? 1965-02-28 00:00:00.000 ? 2016-02-28 00:00:00.000 ?
? Alex Black ? 1960-02-29 00:00:00.000 ? 2016-02-29 00:00:00.000 ?
? Bill Doors ? 1968-02-27 00:00:00.000 ? 2016-02-27 00:00:00.000 ?
??????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)