我正在尝试编写一个存储过程来选择即将到来的生日的员工。
SELECT * FROM Employees WHERE Birthday > @Today AND Birthday < @Today + @NumDays
这不起作用,因为出生年份是生日的一部分,所以如果我的生日是'09 -18-1983',那将不会介于'09 -18-2008'和'09 -25-2008'之间。
有没有办法忽略日期字段的年份部分,只是比较月/日?
这将在每个星期一早上运行,提醒管理人员即将到来的生日,所以它可能会跨越新的一年。
这是我最终创建的工作解决方案,感谢Kogus。
SELECT * FROM Employees
WHERE Cast(DATEDIFF(dd, birthdt, getDate()) / 365.25 as int)
- Cast(DATEDIFF(dd, birthdt, futureDate) / 365.25 as int)
<> 0
答案 0 :(得分:31)
注意:我编辑过这个来修复我认为是一个重要的错误。目前发布的版本适用于我。
在修改字段和表名以与数据库对应后,这应该有效。
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.因此它返回所有这些记录。
答案 1 :(得分:13)
如果有人仍在寻找 MySQL (略有不同的命令)的解决方案,请查询以下内容:
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)
答案 2 :(得分:8)
最好使用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)
答案 3 :(得分:3)
喜欢@strelc的方法,但他的sql有点偏。这是一个运行良好且易于使用的更新版本:
SELECT * FROM User
WHERE (DATEDIFF(dd, getdate(), DATEADD(yyyy,
DATEDIFF(yyyy, birthdate, getdate()) + 1, birthdate)) + 1) % 366 <= <number of days>
编辑10/2017:添加单日结束
答案 4 :(得分:2)
您可以使用DAYOFYEAR
功能,但要在12月份查找1月生日时要小心。只要您所寻找的日期范围不跨越新年,我认为您会没事的。
答案 5 :(得分:2)
我找到了解决方法。这可以节省一些宝贵的时间。
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
与日期交叉加入,并检查月份和日期的比较。
答案 6 :(得分:2)
很抱歉没有看到中和年份的要求。
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)
这应该有用。
答案 7 :(得分:2)
我的猜测是使用&#34; 365.25&#34;很快就会失败。
所以我使用&#34; 365.25&#34;来测试工作解决方案。 并且它不会为每个案例返回相同数量的行。 这是一个例子:
http://sqlfiddle.com/#!3/94c3ce/7
测试2016年和2116年,您将看到差异。我只能发布一个链接但是用/ 8更改de / 7以查看两个查询。 (/ 10和/ 11为第一个答案)
所以,我建议另一个查询,其中点从开始日期确定下一个生日,然后比较它是否在我感兴趣的范围内。
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
答案 8 :(得分:1)
这是MS SQL Server的解决方案: 它会在30天内为员工提供生日。
SELECT * FROM rojstni_dnevi
WHERE (DATEDIFF (dd,
getdate(),
DATEADD ( yyyy,
DATEDIFF(yyyy, rDan, getdate()),
rDan)
nex )
+365) % 365 < 30
答案 9 :(得分: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() ))))
答案 10 :(得分:0)
此解决方案还负责明年的生日和订购: (dob =出生日; bty =今年的生日; nbd =下一个生日)
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
这个避免比较日期的版本可能会更快:
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日,则使用:
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
答案 11 :(得分:0)
我将它用于 MySQL ,可能不是最有效的查询方式,但很容易实现。
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');
答案 12 :(得分:0)
我相信此票已在很久以前关闭,但为了获得正确的SQL查询,请查看。
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))
答案 13 :(得分:0)
更好更简单的解决方案:
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
答案 14 :(得分:0)
SQLite3 的解决方案:
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)的增量。如果今年尚未过生日,您将自动获得正确的剩余天数,您可以将其进行比较。 如果已经过生日,则left_days将为负,并且您仍可以通过添加当年的总天数来获得正确的剩余天数。这样也可以正确处理leap年,因为在这种情况下,还将添加额外的一天(通过使用dayOfYear(Dec 31。))
答案 15 :(得分:0)
您还可以使用DATEPART
:
-- 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))
答案 16 :(得分:0)
当前月份生日
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)
答案 17 :(得分:0)
选择BirthDate,员工姓名 按案例排序 转换时(nvarchar(5),BirthDate,101)&gt;转换(nvarchar(5),GETDATE(),101)然后2 转换时(nvarchar(5),BirthDate,101)&lt;转换(nvarchar(5),GETDATE(),101)然后3 转换(nvarchar(5),BirthDate,101)= convert(nvarchar(5),GETDATE(),101)然后1 else 4 end,convert(nvarchar(2),BirthDate,101),convert(nvarchar(2) ,出生日期,105)
答案 18 :(得分:0)
下面的查询将返回员工的下一个生日,这是最短的查询。
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 ;
以上查询将覆盖下个月的所有月份(当前日期除外)。
答案 19 :(得分:0)
您可以使用DATE_FORMAT来提取生日日期的日期和月份。
编辑:抱歉,我没有看到他没有使用MySQL。答案 20 :(得分:0)
实现同样目标的最佳方法是
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)
答案 21 :(得分:0)
这是经过测试的几个答案的组合。这将在特定日期和它们的年龄之后找到下一个生日。此外,numdays将限制你看7天=一周等的范围。
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
答案 22 :(得分:0)
我希望这会以某种方式帮助你......
select Employeename,DOB
from Employeemaster
where day(Dob)>day(getdate()) and month(DOB)>=month(getDate())
答案 23 :(得分:0)
员工即将到来的生日 - Sqlserver
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)
答案 24 :(得分:0)
螺母!当我开始考虑这个问题和回来回答问题之间的一个很好的解决方案。 :)
我想出了:
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()强制转换为日期时间,对吧?
答案 25 :(得分:0)
尝试一下:
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)
答案 26 :(得分:0)
几年前,我的大学项目面临同样的问题。我通过将年份和日期(MM:DD)分成两个单独的列来回答(以相当狡猾的方式)。在此之前,我的项目伙伴只是简单地获取所有日期并以编程方式通过它们。我们改变了,因为效率太低 - 不是我的解决方案也更优雅。此外,它可能无法在多个应用程序使用一段时间的数据库中执行。
答案 27 :(得分:0)
这应该有用......
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))
答案 28 :(得分:0)
另一个想法:将他们的年龄添加到他们的生日(或者如果他们的生日还没有发生,那么还有一个,然后按照上面的步骤进行比较。使用DATEPART和DATEADD来做到这一点。
http://msdn.microsoft.com/en-us/library/ms186819.aspx
跨越年份的范围的边缘情况必须具有特殊代码。
额外提示:考虑使用BETWEEN ... AND而不是重复生日操作数。
答案 29 :(得分:0)
大多数这些解决方案都很接近,但您必须记住一些额外的方案。使用生日和滑动比例时,您必须能够处理到下个月的过渡。
例如,Stephens示例适用于直到该月的最后4天的生日。然后你有一个逻辑错误作为有效日期,如果今天是29日将是:29,30,然后是NEXT月的1,2,3,所以你也必须为此做好准备。
另一种方法是从生日字段解析日期,然后在当前年份解析,然后进行标准范围比较。
答案 30 :(得分:0)
假设这是T-SQL,请使用DATEPART分别比较月份和日期。
http://msdn.microsoft.com/en-us/library/ms174420.aspx
或者,从每个人的生日中减去当年的1月1日,然后使用1900年(或您的纪元年)进行比较。
答案 31 :(得分:-1)
试试我的解决方案......我有Informix数据库......
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)
答案 32 :(得分:-1)
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
答案 33 :(得分:-2)
更好的是,将年份差异添加到BIRTHDAY日期,今年制作一切,然后进行比较
SELECT * FROM Employees WHERE
DATEADD ( year, YEAR(@Today) - YEAR(@Birthday), birthday) BETWEEN @Today AND @EndDate