SQLselect即将到来的生日
我正在尝试编写一个存储过程来select有即将到来的生日的员工。
SELECT * FROM Employees WHERE Birthday > @Today AND Birthday < @Today + @NumDays
这是行不通的,因为出生年份是生日的一部分,所以如果我的生日是'09 -18-1983',不会在'09-18-2008'和'09-25-2008'之间。
有没有办法忽略年份的date字段,只比较月/日?
这将每星期一上午运行,以提醒pipe理人员即将到来的生日,所以可能会跨越新的一年。
这是我最终创build的工作解决scheme,谢谢Kogus。
SELECT * FROM Employees WHERE Cast(DATEDIFF(dd, birthdt, getDate()) / 365.25 as int) - Cast(DATEDIFF(dd, birthdt, futureDate) / 365.25 as int) <> 0
注:我已经编辑这个来修复我认为是一个重要的错误。 目前发布的版本适合我。
这应该在修改字段和表名称以对应于您的数据库后工作。
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.因此,它返回所有这些logging。
如果有人仍然在MySQL寻找解决scheme(略有不同的命令),这里是查询:
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。 没有四舍五入,没有近似,没有二月二十九号,只有datefunction
-
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是有点closures。 这是一个更新的版本,运行良好,易于使用:
SELECT * FROM User WHERE (DATEDIFF(dd, getdate(), DATEADD(yyyy, DATEDIFF(yyyy, birthdate, getdate()) + 1, birthdate)) + 1) % 366 <= <number of days>
编辑10/2017:添加单日结束
对不起,没有看到中和年的要求。
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)
这应该工作。
我find了解决scheme。 这可以节省一些人的宝贵时间。
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
与date交叉连接,并检查月份和date的比较。
您可以使用DAYOFYEAR
function,但要在12月份查找1月份的生日时要小心。 只要你想找的date范围不包括新年,我想你会没事的。
这是MS SQL Server的解决scheme:它在30天内返回员工生日。
SELECT * FROM rojstni_dnevi WHERE (DATEDIFF (dd, getdate(), DATEADD ( yyyy, DATEDIFF(yyyy, rDan, getdate()), rDan) nex ) +365) % 365 < 30
在不到一个月的时间里:
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() ))))
我的猜测是使用“365.25”不久或将来会失败。
所以我testing使用“365.25”的工作解决scheme,并没有返回每个案件相同数量的行。 这里是一个例子:
http://sqlfiddle.com/#!3/94c3ce/7
testing2016年和2116年,你会看到不同之处。 我只能发布一个链接,但更改de / 7/8查看两个查询。 (/ 10和/ 11的第一个答案)
所以,我build议这个另一个查询,其中点是从一个开始date确定的下一个生日,然后比较它是否在我的兴趣范围内。
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
您可以使用DATE_FORMAT提取生日date的date和月份部分。
编辑:对不起,我没有看到他没有使用MySQL。
假设这是T-SQL,请使用DATEPART分别比较月份和date。
http://msdn.microsoft.com/en-us/library/ms174420.aspx
或者,从每个人的生日中减去当年的1月1日,然后使用1900年(或者无论你的年代)进行比较。
这些解决scheme大部分都很接近,但是您必须记住一些额外的scheme。 在生日和缩放比例下工作时,您必须能够处理到下个月的转换。
例如,斯蒂芬斯(Stephens)的例子在这个月的最后4天之前对生日很有效。 那么如果今天是29日,那么你的逻辑错误是29:30,然后是下一个月的1,2,3,所以你必须考虑到这一点。
另一种方法是parsing生日字段中的date,并在当前年份中进行分析,然后进行标准范围比较。
另一个想法是:把他们的年龄增加到他们的生日(如果他们的生日还没有发生,再加上他们的年龄,然后再比较一下,用DATEPART和DATEADD来做这个。
http://msdn.microsoft.com/en-us/library/ms186819.aspx
年度范围的边缘情况下,必须有特殊的代码。
奖金提示:考虑使用BETWEEN …而不是重复生日操作数。
这应该工作…
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(MM:DD)分成两个单独的列。 在此之前,我的项目伙伴只是简单地获取所有的date,并以编程方式通过它们。 我们改变了这个,因为效率太低了 – 也不是我的解决scheme更优雅。 而且,它可能无法在多个应用程序使用一段时间的数据库中执行。
试试这个:
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)
赶快行动吧! 什么时候开始考虑这个问题,什么时候回来回答。 🙂
我想出了:
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()作为date时间,对吧?
这是被testing的几个答案的组合。 这将会发现在某个date之后的下一个星期几,以及他们的年龄。 此外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
实现这一目标的最好方法是
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)
即将到来的员工生日 – 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)
我使用这个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');
我相信这张票已经closures很久以前,但为了得到正确的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))
更好和简单的解决scheme
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
我希望这可以帮助你以某种方式….
select Employeename,DOB from Employeemaster where day(Dob)>day(getdate()) and month(DOB)>=month(getDate())
这个解决scheme还要照顾下一年的生日和订购:( dob =出生date; 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
这个避免比较date的版本可能会更快:
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
如果范围涵盖明年二月二十九日,则使用:
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
:
-- 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))
本月生日
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)
(nvarchar(5),BirthDate,101)> convert(nvarchar(5),GETDATE(),101)then 2 WHEN convert(nvarchar(5),BirthDate,101)<转换(nvarchar(5),GETDATE(),101)然后3转换(nvarchar(5),BirthDate,101)= convert(nvarchar(5),GETDATE (2),出生date,101),转换(为nvarchar(2),出生date,105)
试试我的解决scheme…我有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)