在一系列日期(截止日期和结束日期)中选择17岁的用户 -
谢谢大家!
用户
示例:
User_1出生日期 09/28/1996
User_2出生日期 08/25/1996
User_3出生日期 07/28/1995
User_4出生日期 05/25/1995
如果日期范围从03/05/2013 到结束日期6/05/2013 * User_1和User_2出现,因为它们符合该时间段内的标准*
无论其
如果范围从02/10/2012 和结束日期06/05/2013 所有用户都应该出现,因为他们在日期范围内的某个时间点都是17
我尝试过使用Datepart(),但我无法清楚地想到得出我想要的答案
Select u.id, u.birthdate
From Users u
where convert(varchar,DATEPART(MM,u.birthdate))<=DATEPART(MM,'03/05/2013')
大家帮忙我得出结论
DATEADD(YY,17,birthdate) between @from and @end
答案 0 :(得分:4)
这些应该这样做;
SELECT * FROM users
WHERE birthdate BETWEEN DATEADD(year, -18, '2013-03-05') -- lo date of range
AND DATEADD(year, -17, '2013-06-05'); -- hi date of range
SELECT * FROM users
WHERE birthdate BETWEEN DATEADD(year, -18, '2012-02-10') -- lo date of range
AND DATEADD(year, -17, '2013-06-05'); -- hi date of range
请注意,User_1在2013年9月28日变为17,在2013年8月25日变为User_2,因此它们都不会(或应该)包含在任何一个范围内。
答案 1 :(得分:2)
我的首选方法:
使用日期数据类型和日期之间的显式比较。我建议将birthdate存储为SQL Server 2008+中的日期数据类型,并使用ISO 8601格式存储日期时间文字以避免歧义。
select id, birthdate
from Users
where birthdate > dateadd(year, -18, '2013-03-05') -- Check lower bounds
and birthdate <= dateadd(year, -17, '2013-06-05'); -- Check upper bounds
请注意,我已将dateadd
函数移动到此修订的常量。正如其他人敏锐地观察到的那样,这意味着更少的计算(除非你只有1行?),并且 - 或许更重要的是 - 允许在出生日期使用指数。
BETWEEN
方法:
如另一个答案所示,使用BETWEEN
可以产生类似的结果:
select id, birthdate
from users
where birthdate between dateadd(year, -18, '2013-03-05')
and dateadd(year, -17, '2013-06-05')
但是,BETWEEN
具有包容性,这意味着它将匹配所有范围,包括端点。在这种情况下,我们会在任何用户的18岁生日上获得匹配,这很可能不是理想的结果(在17到18岁之间通常会有important difference)。我想您可以使用额外的DATEADD
来减去一天,但我希望将BETWEEN
用作Aaron Bertrand suggests时保持一致。
什么不该做:
请勿使用DATEPART
或DATEDIFF
进行此类比较。它们不代表时间跨度。 DATEDIFF
显示边界交叉方面的差异。看看只有一天的下一个年龄会如何显示某人已经一岁,因为这些年份在技术上是分开的:
select datediff(year, '2012-12-31', '2013-01-01'); -- Returns 1!
以这种方式使用'DATEPART'多年的计算会产生相同的结果(类似于月/ 12等,一直到毫秒)。
感谢所有注意到索引可能性的人。我们不要忘记"Make it work, make it right, make it fast."
的序列答案 2 :(得分:-1)
尝试
SELECT *
FROM
Users
WHERE
DATEDIFF(year,@DATE1, '02/10/2012') = 17
OR
DATEDIFF(year,@DATE2, '06/05/2013') =17
将上述@ DATE1和@ DATE2替换为所需日期。