My preferred method:
Use date data types and explicit comparisons between dates. I recommend storing the date of birth as a date type in SQL Server 2008+, and also use the ISO 8601 format for datetime literals to avoid ambiguity.
select id, birthdate from Users where birthdate > dateadd(year, -18, '2013-03-05')
Note that I have moved the dateadd function to constants for this revision. As others have, it means less computation (unless you only had 1 row?) And, perhaps more importantly, it allows you to use the index by date of birth.
BETWEEN Method:
As shown in another answer, using BETWEEN can give a similar result:
select id, birthdate from users where birthdate between dateadd(year, -18, '2013-03-05') and dateadd(year, -17, '2013-06-05')
However, BETWEEN is inclusive, meaning it will fit the entire range, including end points. In this case, we will get a match for any user on their 18th birthday , which is most likely not the desired result (often there is an important age difference from 17 to 18 years). I suppose you could use an extra dateadd to subtract the day, but I like to be consistent in my use of BETWEEN as Aaron Bertrand suggests .
What not to do:
Do not use DATEPART or DATEDIFF for this type of comparison. They do not represent a time frame. DATEDIFF shows the difference in terms of crossed boundaries. See how the next age of only one day will show that someone is already a year, because the years are technically one from each other:
select datediff(year, '2012-12-31', '2013-01-01');
Calculation using "DATEPART" for many years in the same way will give the same thing (similar to months / 12, etc., up to milliseconds).
Thanks to everyone who noted the possibility of indexing. Let's just not forget the βMake it work, do it right, do it fastβ sequence .