关于sql server:SQL选择即将到来的生日

关于sql server:SQL选择即将到来的生日

SQL Select Upcoming Birthdays

我正在尝试编写一个存储过程来选择即将过生日的员工。

SELECT * FROM Employees WHERE Birthday > @Today AND Birthday < @Today + @NumDays

这将不起作用,因为出生年份是生日的一部分,因此,如果我的生日是" 09-18-1983",则不会在" 09-18-2008"和" 09-25-2008"之间。

有没有办法忽略日期字段的年份部分,而只比较月份/天数?

该程序将在每个星期一早上运行,以提醒管理人员即将到来的生日,因此它可能跨越新的一年。

感谢Kogus,这是我最终创建的有效解决方案。

1
2
3
4
SELECT * FROM Employees
WHERE CAST(DATEDIFF(dd, birthdt, getDate()) / 365.25 AS INT)
    - CAST(DATEDIFF(dd, birthdt, futureDate) / 365.25 AS INT)
<> 0


注意:我已经对其进行了编辑,以修复我认为是重要的错误。当前发布的版本适用于我。

在修改字段和表名称以使其与数据库相对应后,此方法应该起作用。

1
2
3
4
5
6
7
8
9
SELECT
  BRTHDATE AS BIRTHDAY
 ,FLOOR(DATEDIFF(dd,EMP.BRTHDATE,GETDATE()) / 365.25) AS AGE_NOW
 ,FLOOR(DATEDIFF(dd,EMP.BRTHDATE,GETDATE()+7) / 365.25) AS AGE_ONE_WEEK_FROM_NOW
FROM
 "Database name".dbo.EMPLOYEES EMP
WHERE 1 = (FLOOR(DATEDIFF(dd,EMP.BRTHDATE,GETDATE()+7) / 365.25))
          -
          (FLOOR(DATEDIFF(dd,EMP.BRTHDATE,GETDATE()) / 365.25))

基本上,它获得从生日到现在的天数,并将其除以365(以避免舍入直接转换为年份时出现的问题)。

然后将其从生日到现在的一周的天数,然后将其除以365,从现在开始一周。

如果他们的生日在一周之内,则这两个值之间的差将为1。因此,它将返回所有这些记录。


如果有人仍在寻找MySQL解决方案(略有不同的命令),请执行以下查询:

1
2
3
4
5
6
7
8
9
10
SELECT
 name,birthday,
 FLOOR(DATEDIFF(DATE(NOW()),birthday) / 365.25) AS age_now,
 FLOOR(DATEDIFF(DATE_ADD(DATE(NOW()),INTERVAL 30 DAY),birthday) / 365.25) AS age_future

FROM USER

WHERE 1 = (FLOOR(DATEDIFF(DATE_ADD(DATE(NOW()),INTERVAL 30 DAY),birthday) / 365.25)) - (FLOOR(DATEDIFF(DATE(NOW()),birthday) / 365.25))

ORDER BY MONTH(birthday),DAY(birthday)

最好使用datediff和dateadd。没有四舍五入,没有近似值,没有2月29日的bug,仅是日期函数

  • ageOfThePerson = DATEDIFF(yyyy,dateOfBirth, GETDATE())

  • dateOfNextBirthday = DATEADD(yyyy,ageOfThePerson + 1, dateOfBirth)

  • daysBeforeBirthday = DATEDIFF(d,GETDATE(), dateofNextBirthday)

  • 感谢@Gustavo Cardoso,此人的年龄有了新定义

  • ageOfThePerson = FLOOR(DATEDIFF(d,dateOfBirth, GETDATE())/365.25)

  • 喜欢@strelc的方法,但是他的sql有点问题。这是一个运行良好且易于使用的更新版本:

    1
    2
    3
    SELECT * FROM USER
    WHERE (DATEDIFF(dd, getdate(), DATEADD(yyyy,
        DATEDIFF(yyyy, birthdate, getdate()) + 1, birthdate)) + 1) % 366 <= <NUMBER OF days>

    编辑10/2017:添加一天到结束


    我的猜测是不久以后使用" 365.25"将失败。

    因此,我使用" 365.25"测试了工作解决方案
    而且它不会为每种情况返回相同数量的行。
    这里是一个例子:

    http://sqlfiddle.com/#!3/94c3ce/7

    用2016年和2116年进行测试,您会看到不同。我只能发布一个链接,但将de / 7更改为/ 8才能看到两个查询。 (第一个答案为/ 10和/ 11)

    因此,我建议这是另一个查询,要点是从开始日期确定下一个生日,然后比较是否在我感兴趣的范围内。

    1
    2
    3
    4
    5
    6
    SELECT * FROM Employees
    WHERE
    CASE WHEN (DATEADD(yyyy,DATEDIFF(yyyy, birthdt, @fromDate),birthdt) < @fromDate )
    THEN DATEADD(yyyy,DATEDIFF(yyyy, birthdt, @fromDate)+1,birthdt)
    ELSE DATEADD(yyyy,DATEDIFF(yyyy, birthdt, @fromDate),birthdt) END
    BETWEEN @fromDate AND @toDate

    抱歉,没有看到中和年份的要求。

    1
    2
    3
    4
    SELECT * FROM Employees
    WHERE DATEADD (YEAR, DatePart(YEAR, getdate()) - DatePart(YEAR, Birthday), Birthday)
          BETWEEN CONVERT(datetime, getdate(), 101)
                  AND CONVERT(datetime, DateAdd(DAY, 5, getdate()), 101)

    这应该工作。


    我找到了解决方案。这样可以节省某人的宝贵时间。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     SELECT EmployeeID,DOB,dates.date  FROM emp_tb_eob_employeepersonal
     CROSS JOIN dbo.GetDays(Getdate(),Getdate()+7) AS dates WHERE weekofmonthnumber>0
     AND MONTH(dates.date)=MONTH(DOB) AND DAY(dates.date)=DAY(DOB)



    GO
    /****** Object:  UserDefinedFunction [dbo].[GetDays]    Script Date: 11/30/2011 13:19:17 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    --SELECT [dbo].[GetDays] ('02/01/2011','02/28/2011')

    ALTER FUNCTION [dbo].[GetDays](@startDate datetime, @endDate datetime)
    RETURNS @retValue TABLE
    (Days INT ,DATE datetime, WeekOfMonthNumber INT, WeekOfMonthDescription VARCHAR(10), DayName VARCHAR(10))
    AS
    BEGIN
        DECLARE @nextDay INT
        DECLARE @nextDate datetime
        DECLARE @WeekOfMonthNum INT
        DECLARE @WeekOfMonthDes VARCHAR(10)
        DECLARE @DayName VARCHAR(10)
        SELECT @nextDate = @startDate, @WeekOfMonthNum = DATEDIFF(week, DATEADD(MONTH, DATEDIFF(MONTH,0,@startDate),0),@startDate) + 1,
        @WeekOfMonthDes = CASE @WeekOfMonthNum
            WHEN '1' THEN 'First'
            WHEN '2' THEN 'Second'
            WHEN '3' THEN 'Third'
            WHEN '4' THEN 'Fourth'
            WHEN '5' THEN 'Fifth'
            WHEN '6' THEN 'Sixth'
            END,
        @DayName
        = DATENAME(weekday, @startDate)
    SET @nextDay=1
    WHILE @nextDate <= @endDate
    BEGIN
        INSERT INTO @retValue VALUES (@nextDay,@nextDate, @WeekOfMonthNum, @WeekOfMonthDes, @DayName)
        SELECT @nextDay=@nextDay + 1
    SELECT @nextDate = DATEADD(DAY,1,@nextDate),
        @WeekOfMonthNum
        = DATEDIFF(week, DATEADD(MONTH, DATEDIFF(MONTH,0, @nextDate),0), @nextDate) + 1,
        @WeekOfMonthDes
        = CASE @WeekOfMonthNum
        WHEN '1' THEN 'First'
        WHEN '2' THEN 'Second'
        WHEN '3' THEN 'Third'
        WHEN '4' THEN 'Fourth'
        WHEN '5' THEN 'Fifth'
        WHEN '6' THEN 'Sixth'
        END,
        @DayName
        = DATENAME(weekday, @nextDate)
        CONTINUE
    END

    WHILE(@nextDay <=31)
    BEGIN


        INSERT INTO @retValue VALUES (@nextDay,@nextDate, 0, '', '')
        SELECT @nextDay=@nextDay + 1

    END

        RETURN
    END

    对日期进行交叉连接,然后检查月份和日期的比较。


    您可以使用DAYOFYEAR函数,但是要查找十二月的一月生日时要小心。只要您要的日期范围不跨过新年,我认为您就可以了。


    在不到一个月的时间内:

    1
    SELECT * FROM people WHERE MOD( DATEDIFF( CURDATE( ) , `date_birth`) /30, 12 ) <1 AND (((MONTH(`date_birth`)) = (MONTH(curdate())) AND (DAY(`date_birth`)) > (DAY (curdate() ))) OR ((MONTH(`date_birth`)) > (MONTH(curdate())) AND (DAY(`date_birth`)) < (DAY (curdate() ))))

    这是MS SQL Server的解决方案:
    它会在30天内为员工送上生日。

    1
    2
    3
    4
    5
    6
    7
    8
    SELECT * FROM rojstni_dnevi
      WHERE (DATEDIFF   (dd,
                        getdate(),
                        DATEADD (   yyyy,
                                    DATEDIFF(yyyy, rDan, getdate()),
                                    rDan)
        nex             )
            +365) % 365 < 30

    另一个想法是:将他们的年龄加到他们的生日中(如果还没有生日,则再增加一个,然后像上面一样进行比较。请使用DATEPART和DATEADD进行此操作。

    http://msdn.microsoft.com/en-us/library/ms186819.aspx

    跨年范围的边缘情况必须具有特殊代码。

    温馨提示:考虑使用BETWEEN ... AND而不是重复Birthday操作数。


    这些解决方案中的大多数都很接近,但是您必须记住一些其他方案。在处理生日和缩放比例时,您必须能够处理到下个月的过渡。

    例如,斯蒂芬斯(Stephens)示例非常适合生日,直到一个月的最后4天为止。然后,如果今天是29日,则存在逻辑错误,因为有效日期将是:29、30,然后是下一个月的1、2、3,因此您也必须对此进行限制。

    一种替代方法是解析生日字段中的日期,并将其细分为当前年份,然后进行标准范围比较。


    我希望这可以在某种程度上帮助您。

    1
    2
    3
    SELECT Employeename,DOB
    FROM Employeemaster
    WHERE DAY(Dob)>DAY(getdate()) AND MONTH(DOB)>=MONTH(getDate())

    几年前,我在大学项目中遇到了同样的问题。我通过将年份和日期(MM:DD)分为两个单独的列来做出响应(以一种相当狡猾的方式)。在此之前,我的项目伙伴只是获取所有日期并以编程方式遍历它们。我们更改了它是因为它效率太低-也不是说我的解决方案也更优雅。另外,在多个应用程序使用了一段时间的数据库中,可能无法做到这一点。


    试试看:

    1
    2
    3
    SELECT * FROM Employees
    WHERE DATEADD(yyyy, DATEPART(yyyy, @Today)-DATEPART(yyyy, Birthday), Birthday) > @Today
    AND DATEADD(yyyy, DATEPART(yyyy, @Today)-DATEPART(yyyy, Birthday), Birthday) < DATEADD(dd, @NumDays, @Today)

    假设这是T-SQL,请使用DATEPART分别比较月份和日期。

    http://msdn.microsoft.com/en-us/library/ms174420.aspx

    或者,从每个人的生日中减去当前年份的1月1日,然后使用1900年(或任何纪元年份)进行比较。


    坚果!在我开始考虑这个问题和回来回答之间一个很好的解决方案。 :)

    我想出了:

    1
    2
    3
    SELECT  (365 + datediff(d,getdate(),CAST(CAST(datepart(yy,getdate()) AS VARCHAR(4)) + '-' + CAST(datepart(m,birthdt) AS VARCHAR(2)) + '-' + CAST(datepart(d,birthdt) AS VARCHAR(2)) AS datetime))) % 365
    FROM    employees
    WHERE   (365 + datediff(d,getdate(),CAST(CAST(datepart(yy,getdate()) AS VARCHAR(4)) + '-' + CAST(datepart(m,birthdt) AS VARCHAR(2)) + '-' + CAST(datepart(d,birthdt) AS VARCHAR(2)) AS datetime))) % 365 < @NumDays

    您不需要将getdate()转换为日期时间,对吗?


    员工即将到来的生日-SQLServer

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    DECLARE @sam TABLE
    (
        EmployeeIDs     INT,
        dob         datetime
    )
    INSERT INTO @sam (dob, EmployeeIDs)
    SELECT DOBirth, EmployeeID FROM Employee

    SELECT *
    FROM
    (
        SELECT *, bd_this_year = DATEADD(YEAR, DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, dob), dob)
        FROM @sam s
    ) d
    WHERE d.bd_this_year > DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
    AND d.bd_this_year <= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 3)

    这应该工作...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    DECLARE @endDate DATETIME
    DECLARE @today DATETIME

    SELECT @endDate = getDate()+6, @today = getDate()

    SELECT * FROM Employees
        WHERE
        (DATEPART (MONTH, birthday) >= DATEPART (MONTH, @today)
            AND DATEPART (DAY, birthday) >= DATEPART (DAY, @today))
        AND
        (DATEPART (MONTH, birthday) < DATEPART (MONTH, @endDate)
            AND DATEPART (DAY, birthday) < DATEPART (DAY, @endDate))

    您可以使用DATE_FORMAT提取生日日期的日期和月份部分。

    编辑:对不起,我没有看到他没有使用MySQL。


    实现相同目标的最佳方法是

    1
    2
    3
    4
    5
    6
    7
    DECLARE @StartDate DATETIME
    DECLARE @EndDate DATETIME

    SELECT Member.* FROM vwMember AS Member  
    WHERE (DATEADD(YEAR, (DATEPART(YEAR, @StartDate) -
                          DATEPART(YEAR, Member.dBirthDay)), Member.dBirthDay)
    BETWEEN @StartDate AND @EndDate)

    SQLite3的解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT
        *,
        strftime('%j', birthday) - strftime('%j', 'now') AS days_remaining
    FROM
        person
    WHERE :n_days >= CASE
        WHEN days_remaining >= 0 THEN days_remaining
        ELSE days_remaining + strftime('%j', strftime('%Y-12-31', 'now'))
        END
    ;

    解决方案除以325.25来获取年龄,或将生日设为当前年份等对我不起作用。
    这是计算两天的年(1-366)的增量。如果今年尚未过生日,您将自动获得正确的剩余天数,您可以将其进行比较。
    如果已经过生日,则剩余天数将为负数,并且您仍可以通过添加当年的总天数来获得正确的剩余天数。这也可以正确处理leap年,因为在这种情况下,还将添加额外的一天(通过使用dayOfYear(Dec 31.))


    我将它用于MySQL,可能不是最有效的查询方式,但实施起来却很简单。

    1
    SELECT * FROM `schema`.`table` WHERE date_format(birthday,'%m%d') >= date_format(now(),'%m%d') AND date_format(birthday,'%m%d') < date_format(DATE_ADD(NOW(), INTERVAL 5 DAY),'%m%d');

    我相信这张票已经关闭很久了,但是为了获得正确的SQL查询,请看看。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SELECT Employee_Name, DATE_OF_BIRTH
    FROM Hr_table
    WHERE

    /**
    fetching the original birth_date and replacing the birth year to the current but have to  deduct 7 days to adjust jan 1-7 birthdate.
    **/


    datediff(d,getdate(),DATEADD(YEAR,datediff(YEAR,DATEADD(d,-7,hr.DATE_OF_BIRTH),getdate()),hr.date_of_birth)) BETWEEN 0 AND 7

    -- current date looks ahead to 7 days for upcoming modified year birth date.

    ORDER BY

    -- sort by no of days before the birthday
    datediff(d,getdate(),DATEADD(YEAR,datediff(YEAR,DATEADD(d,-7,hr.DATE_OF_BIRTH),getdate()),hr.date_of_birth))

    更好,更简单的解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT * FROM users WITH(nolock)
    WHERE date_of_birth IS NOT NULL
    AND
    (
          DATEDIFF(dd,
                      DATEADD(yy, -(YEAR(GETDATE())-1900),GETDATE()), --Today
                      DATEADD(yy, -(YEAR(date_of_birth)-1901),date_of_birth)
          ) % 365
    ) = 30

    此解决方案还照顾明年的生日和订购:
    (出生日期=出生日期;出生日期=今年的生日;出生日期=下一个生日)

    1
    2
    3
    4
    5
    6
    7
    WITH rs (bty) AS (
        SELECT DATEADD(YEAR, DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, dob), dob) AS bty FROM Employees
    ),
    rs2 (nbd) AS (
      SELECT CASE WHEN bty < getdate() THEN DATEADD(yyyy, 1, bty) ELSE bty END AS nbd FROM rs
    )
    SELECT nbd, DATEDIFF(d, getdate(), nbd) AS diff FROM rs2 WHERE DATEDIFF(d, getdate(), nbd) < 14 ORDER BY diff

    该版本避免了日期的比较,可能会更快:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    WITH rs (dob, bty) AS (
        SELECT dob, DATEADD(YEAR, DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, DOB), DOB) AS bty FROM employee
    ),
    rs2 (dob, nbd) AS (
      SELECT dob,  DATEADD(yyyy, FLOOR(ABS((-1*(SIGN(DATEDIFF(d, getdate(), bty))))+0.1)), bty) AS nbd FROM rs
    ),
    rs3 (dob, diff) AS (
      SELECT dob, datediff(d, getdate(), nbd) AS diff FROM rs2
    )
    SELECT dob, diff  FROM rs3 WHERE diff < 14 ORDER BY diff

    如果范围涵盖下一年的2月29日,请使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    WITH rs (dob, ydiff) AS (
      SELECT dob, DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, DOB) AS ydiff FROM Employee
    ),
    rs2 (dob, bty, ydiff) AS (
      SELECT dob, DATEADD(YEAR, ydiff, dob) AS bty, ydiff FROM rs
    ),
    rs3 (dob, nbd) AS (
      SELECT dob, DATEADD(yyyy, FLOOR(ABS((-1*(SIGN(DATEDIFF(d, getdate(), bty))))+0.1)) +  ydiff, dob) AS nbd FROM rs2
    ),
    rs4 (dob, ddiff, nbd) AS (
      SELECT dob, datediff(d, getdate(), nbd) AS diff, nbd FROM rs3
    )
    SELECT dob, nbd, ddiff FROM rs4 WHERE ddiff < 68 ORDER BY ddiff

    您也可以使用DATEPART

    1
    2
    3
    4
    5
    6
    7
    8
    -- To find out Today's Birthday
    DECLARE @today DATETIME
    SELECT  @today = getdate()

    SELECT *
    FROM SMIS_Registration
    WHERE (DATEPART (MONTH, DOB) >= DATEPART (MONTH, @today)
          AND DATEPART (DAY, DOB) = DATEPART (DAY, @today))

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT BirthDate,Name FROM Employees
    ORDER BY
    CASE WHEN CONVERT(nvarchar(5),BirthDate,101) > CONVERT(nvarchar(5),GETDATE(),101)
         THEN 2
         WHEN CONVERT(nvarchar(5),BirthDate,101) < CONVERT(nvarchar(5),GETDATE(),101)
         THEN 3
         WHEN CONVERT(nvarchar(5),BirthDate,101) = CONVERT(nvarchar(5),GETDATE(),101)
         THEN 1
         ELSE 4 END,
    CONVERT(nvarchar(2),BirthDate,101),CONVERT(nvarchar(2),BirthDate,105)

    下面的查询将返回员工的所有下一个生日,这是最短的查询。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    SELECT
        Employee.DOB,
        DATEADD(
                    mm,
                    (
                        (
                            (
                                (
                                    DATEPART(yyyy, getdate())-DATEPART(yyyy, Employee.DOB )
                                )
                                +
                                (
                                    1-
                                    (
                                        ((DATEPART(mm, Employee.DOB)*100)+DATEPART(dd, Employee.DOB))
                                        /
                                        ((DATEPART(mm, getdate())*100) + DATEPART(dd, getdate()))
                                    )
                                )
                            )
                        *12
                        )
                    ),
                    Employee.DOB
                ) NextDOB
    FROM
        Employee
    ORDER BY
        NextDOB ;

    以上查询将覆盖下个月的所有月份(当前日期除外)。


    这是经过测试的几个答案的组合。这将在特定日期及其年龄之后的下一个生日。 numdays也将限制您要查找的范围7天=周等。

    1
    2
    3
    4
    5
    6
    SELECT DISTINCT FLOOR(DATEDIFF(dd,Birthday, @BeginDate) / 365.25) + 1 age,
    DATEADD(yyyy, FLOOR(DATEDIFF(dd,Birthday, @BeginDate) / 365.25) + 1, Birthday) nextbirthday, birthday
    FROM         TABLE
    WHERE     DATEADD(yyyy, FLOOR(DATEDIFF(dd,Birthday, @BeginDate) / 365.25) + 1, Birthday) > @BeginDate  
    AND DATEADD(yyyy, FLOOR(DATEDIFF(dd,Birthday, @BeginDate) / 365.25) + 1, Birthday) < DATEADD(dd, @NumDays, @BeginDate)
    ORDER BY nextbirthday


    尝试我的解决方案...我有Informix数据库...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    SELECT person, YEAR(today)-YEAR(birthdate) AS years, birthdate,

    CASE
    WHEN MOD(YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1),4)<>0 AND MONTH(birthdate)=2 AND DAY(birthdate)=29 THEN
       CASE
       WHEN mdy(MONTH(birthdate), 28, YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1))-today >= 365 THEN (mdy(MONTH(birthdate), 28, YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1))-today)-365
       WHEN mdy(MONTH(birthdate), 28, YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1))-today < 365 THEN mdy(MONTH(birthdate), 28, YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1))-today
       END
    ELSE
       CASE
       WHEN mdy(MONTH(birthdate), DAY(birthdate), YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1))-today >= 365 THEN (mdy(MONTH(birthdate), DAY(birthdate), YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1))-today)-365
       WHEN mdy(MONTH(birthdate), DAY(birthdate), YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1))-today < 365 THEN mdy(MONTH(birthdate), DAY(birthdate), YEAR(birthdate)+((YEAR(today)-YEAR(birthdate))+1))-today
       END
    END until

    FROM TABLE_NAME
    WHERE mdy(MONTH(birthdate), DAY(birthdate), 2000) >= mdy(MONTH(today), DAY(today), 2000)
    AND mdy(MONTH(birthdate), DAY(birthdate), 2000) <= mdy(MONTH(today), DAY(today), 2000)+30
    OR
    mdy(MONTH(birthdate), DAY(birthdate), 2000) <= mdy(MONTH(today), DAY(today), 2000)-(365-30)
    ORDER BY 4, YEAR(birthdate)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    CREATE PROCEDURE [dbo].[P_EmployeesGetBirths]
            @DATE DATE,
            @Days INT
        AS
        BEGIN
            SET NOCOUNT ON;

            DECLARE
                @FROM INT = MONTH(@DATE) * 100 + DAY(@DATE),
                @TO INT = MONTH(DateAdd(DD, @Days, @DATE)) * 100 + DAY(DateAdd(DD, @Days, @DATE)),
                @NeutralDate DATE = CAST('1900-'+CAST(MONTH(@DATE) AS nvarchar(2))+'-' + CAST(DAY(@DATE) AS nvarchar(2)) AS DATE)

            SELECT
                DOB,
                DATEADD(DD, DateDiff(DD, @NeutralDate, DateAdd(YY, 1900-YEAR(DOB), DOB)), @DATE) OnDate
            FROM
                Employees(nolock)
            WHERE
                DOB IS NOT NULL AND
                MONTH(DOB) * 100 + DAY(DOB) BETWEEN @FROM AND @TO
            ORDER BY
                MONTH(DOB) * 100 + DAY(DOB)
        END
        GO

    当前月份生日

    1
    2
    3
    4
    SELECT * FROM tblMember m
    WHERE m.GDExpireDate != ''
    AND CONVERT(CHAR(2),CONVERT(datetime, m.dob, 103), 101) = CONVERT(CHAR(2), GETDATE(), 101)    
    AND CONVERT(CHAR(2),CONVERT(datetime, m.dob, 103), 103) >= CONVERT(CHAR(2), GETDATE(), 103)

    更好的做法是,在BIRTHDAY日期加上年份之间的差值,以完成今年的所有工作,然后进行比较

    1
    2
    SELECT * FROM Employees WHERE
      DATEADD ( YEAR, YEAR(@Today) - YEAR(@Birthday), birthday) BETWEEN @Today AND @EndDate

    推荐阅读