In the users table I have birth_date column. I want to select only users under the age 18.
I tried using alias
select
*,
age = case
when datediff(year, getdate(), birth_date) > 0
then year(getdate()) - year(birth_date) - 1
else year(getdate()) - year(birth_date)
end
from
users
where
age < 18
But apparently I cannot use alias in where.
So I tried using case but it's also not gonna work
select *
from users
where
case
when datediff(year, getdate(), birth_date) > 0
then year(getdate()) - year(birth_date) - 1 < 18
else year(getdate()) - year(birth_date) < 18
What shall I do in this case? I don't want to use a stored procedure.
Use cte
WITH cte AS
(
SELECT *,
CASE
WHEN DATEDIFF(year, getdate(), birth_date) > 0
THEN year(getdate()) - year(birth_date) - 1
ELSE year(getdate()) - year(birth_date)
END AS age
FROM users
)
SELECT *
FROM cte
WHERE age < 18
demo in db<>fiddle
The correct way to do this is not to use DATEDIFF at all. It will be less accurate (as it uses date boundaries) and slower (it can't use indexes).
Instead use DATEADD against the current date, do not use functions against the column
SELECT *
FROM dbo.users
WHERE birth_date > DATEADD(year, -18, GETUTCDATE()) -- maybe cast right-side to DATE?
db<>fiddle
simple use this !
SELECT * FROM dbo.users WHERE DATEDIFF(day,birth_date,GETDATE()) < 6570
I think you're just looking for direction on how to use an alias/CASE statement in a column?
If that's correct, then you'll just need to surround your alias with brackets.
select *
,case
when datediff(year, getdate(), birth_date) > 0
then year(getdate()) - year(birth_date) - 1
else year(getdate()) - year(birth_date)
end as age
from users
where age < 18
Below is one way to calculate age which accounts for leap days and other complexities. This calculates the difference of the yyyymmdd integer values and then divides by 10000 to evaluate only the year difference.
SELECT *
FROM users
WHERE
(CAST(FORMAT(GETDATE(), 'yyyyMMdd') AS int) -
CAST(FORMAT(birth_date, 'yyyyMMdd') AS int)) / 10000 < 18;
Related
I have a table with birthdates and I want to select all the birthdays that will come in the next 30 days.
The situation is, that all the birthdays are written in the form off 1999-09-15 which means that even if I tried selecting the next 30 days, the birthdays wouldn't show up because the year is 1999.
I am running Microsoft Server 2016.
SELECT * from dbo.EMPLOYEES
WHERE DATE <= DATEADD(day, +30,GETDATE())
and DATE >= getdate()
order by "DATE"
To get the birthdate, we need to work only on the days and the months, not on the year. Thats why we cannot get Where date between 2 dates.
SELECT
dateofbirth_c AS BIRTHDAY
,FLOOR(DATEDIFF(dd,EMP.dateofbirth_c,GETDATE()) / 365.25) AS AGE_NOW
,FLOOR(DATEDIFF(dd,EMP.dateofbirth_c,GETDATE()+30) / 365.25) AS AGE_30_Days_FROM_NOW
FROM
Employees EMP
WHERE 1 = (FLOOR(DATEDIFF(dd,EMP.dateofbirth_c,GETDATE()+30) / 365.25))
-
(FLOOR(DATEDIFF(dd,EMP.dateofbirth_c,GETDATE()) / 365.25))
Try the following; check the month and day because year will not match with birthday year that's why you are not getting any data.
SELECT *
from dbo.EMPLOYEES
WHERE month(DATE)>= month(GETDATE())
and day(DATE) >= day (getdate()) and day(DATE) < = day( getdate()) + 30
order by "DATE"
I'm note sure about microsoft server but on postgres just generate list of days and compare like this.
SELECT * FROM table WHERE to_char(user_dob, 'MM-DD') IN
(SELECT to_char(date, 'MM-DD')
FROM generate_series(current_date, current_date + 30, '1 day') AS date);
And now all you have to change that 30 to any days to make it work.
try this
SELECT *
FROM dbo.EMPLOYEES
WHERE DATEFROMPARTS(YEAR(GETDATE()) , MONTH(Date), DAY(Date)) >= GETDATE()
AND DATEFROMPARTS(YEAR(GETDATE()) , MONTH(Date), DAY(Date)) <= DATEADD(day, +30, GETDATE())
ORDER BY Date
If you want an accurate result that works for leap years and so on, then:
SELECT e.*
FROM dbo.EMPLOYEES e CROSS APPLY
(VALUES (DATEFROMPARTS(YEAR(GETDATE()),
MONTH(e.date),
DAY(e.date)
)
)
) v(this_year_date)
WHERE DATEDIFF(day, GETDATE(), this_year_date) BETWEEN 0 AND 29 OR
DATEDIFF(day, GETDATE(), DATEADD(year, 1, this_year_date)) BETWEEN 0 AND 29
order by "DATE"
I have a query that works but I need to incorporate in that query the following:
For male date is older or equals 3 months;
For female date is older or equals 4 months;
SELECT *
FROM Davaoci
WHERE DatumPoslednjegDavanja >= DATEADD(month, -3, GETDATE())
AND KrvnaGrupa = 'APos'
ORDER BY DatumPoslednjegDavanja DESC
Use a CASE statement:
SELECT * FROM Davaoci
WHERE DatumPoslednjegDavanja >= DATEADD(
month,
CASE WHEN Pol = 'M' THEN -3 ELSE -4 END,
GETDATE()
)
AND KrvnaGrupa = 'APos'
ORDER BY DatumPoslednjegDavanja DESC
EDITED: Based off your comments on the question, I made some adjustments to my answer. Working through our language barrier, I think this is what you're looking for.
NOTE: The way I have this set up now, it will only accept rows where the Pol column has an 'M' or 'F'. You may need to adjust the ELSE as needed.
SELECT *
FROM Davaoci
WHERE
KrvnaGrupa = 'APos'
AND CASE
WHEN Pol = 'M'
THEN DatumPoslednjegDavanja >= DATEADD(month, -3, GETDATE())
WHEN Pol = 'F'
THEN DatumPoslednjegDavanja <= DATEADD(month, -4, GETDATE())
ELSE FALSE
END
ORDER BY
DatumPoslednjegDavanja DESC;
I have following task:
Show the list of first, last names and ages of the employees whose age
is greater than 55. The result should be sorted by last name.
This is my code:
SELECT
LastName, FirstName,
(CASE
WHEN (CONVERT(INT, GETDATE()) - CONVERT(INT, BirthDate)) > 55
THEN CONVERT(INT, GETDATE()) - CONVERT(INT, BirthDate)
END) as Age
FROM
Employees
ORDER BY
LastName
This is what I get:
This is the BirthDate table (datetime):
Why does the age go so crazy? What's wrong?
For age, use expression
DateDiff(year, birthdate, getdate()) +
case when Month(getdate()) > Month(birthdate)
or Day(getdate()) >= Day(birthdate)
then 1 else 0 end
i.e.,
SELECT LastName, FirstName,
DateDiff(year, birthdate, getdate()) +
case when Month(getdate()) > Month(birthdate)
or Day(getdate()) >= Day(birthdate)
then 1 else 0 end Age
FROM Employees
where DateDiff(year, birthdate, getdate()) +
case when Month(getdate()) > Month(birthdate)
or Day(getdate()) >= Day(birthdate)
then 1 else 0 end > 55
ORDER BY LastName
SELECT *
FROM
(SELECT
LastName, FirstName,
(CASE
WHEN DATEDIFF(yy, BirthDate, GETDATE()) > 55
THEN DATEDIFF(yy, BirthDate, GETDATE())
ELSE 0
END) AS Age
FROM
Employees) AS ABC
WHERE
ABC.Age != 0
ORDER BY
ABC.LastName
Problem in your result is you are converting Date to int and you didn't convert the Int back to Date
Add the filter in Where clause. To calculate age I always use below method
SELECT FLOOR(DATEDIFF(DAY, '1990-07-20', getdate()) / 365.25)
Result : 26
SELECT LastName,
FirstName,
Floor(Datediff(DAY, BirthDate, Getdate()) / 365.25) AS Age
FROM Employees
WHERE Floor(Datediff(DAY, BirthDate, Getdate()) / 365.25) > 55
ORDER BY LastName
I strongly advise you to not use datediff(). It does not work intuitively. It counts the number of year boundaries between two dates. Although there is a relationship between New Year's celebrations and age, the two are not equivalent.
Instead:
SELECT LastName, FirstName
FROM Employees
WHERE birthdate < DATEADD(year, -55, getdate())
ORDER BY LastName;
Unfortunately, that doesn't get the age. That is a bit tricky. You could use datediff() just to be "close enough". The exactly logic is a bit of a pain. I would refer you here.
I want to convert the DOB into the number age, then assign the age value into different age groups on SQL Server.
I have found the way to do the first step, and the second step ideally I should set the first step's result as a variable and let it compare in the CASE statement. However, I don't know declare and set the variable and use it in CASE.
I got the table I want with a silly way as below:
SELECT FirstName, LastName,
CAST(
CASE
WHEN FLOOR((CAST (GetDate() AS INTEGER) - CAST(dob AS INTEGER)) / 365.25) < 18
THEN 'Under 18'
WHEN FLOOR((CAST (GetDate() AS INTEGER) - CAST(dob AS INTEGER)) / 365.25) BETWEEN 19 AND 30
THEN '19-30'
WHEN FLOOR((CAST (GetDate() AS INTEGER) - CAST(dob AS INTEGER)) / 365.25) > 30
THEN 'Over 30'
ELSE 'ERROR'
END AS VARCHAR(10)) AS Age
FROM Student
MY QUESTION: Is there a way to set "FLOOR((CAST (GetDate() AS INTEGER) - CAST(DOB AS INTEGER)) / 365.25)" as a variable and use it in the CASE statement?
*FirstName, LastName and dbo are columns in Student Table.
Thank you!
No, not in the case statement. The two traditional recommendations are to use CTEs or subqueries. But, SQL Server also supports apply:
SELECT FirstName, LastName,
(CASE WHEN v.age <= 18 THEN 'Under 18'
WHEN v.age <= 30 THEN '19-30'
WHEN v.age > 30 THEN 'Over 30'
ELSE 'ERROR'
END) AS Age
FROM Student s OUTER APPLY
(VALUES (FLOOR((CAST (GetDate() AS INTEGER) - CAST(dob AS INTEGER)) / 365.25) )
) as v(age);
Comments:
You don't need to cast strings to varchar(10). That is just superfluous.
The case is evaluated in order, so you don't need between. This makes it much easier if you want to change the boundaries.
I have a scenario in which I have to get those users whose age is between say (10 - 20) in sql, I have a column with date of birth dob. By executing the below query I get the age of all users.
SELECT
FLOOR((CAST (GetDate() AS INTEGER) - CAST(dob AS INTEGER)) / 365.25) AS Age
FROM users
My question is how should I write my query so that I can get that users whose age is between 10 to 20
I don't have a SQL-Server available to test right now. I'd try something like:
select * from users where datediff(year, dob, getdate()) between 10 and 20;
First add computed field Age like you already did. Then make where filtering on the data.
SELECT * FROM
(SELECT FLOOR((CAST (GetDate() AS INTEGER) - CAST(dob AS INTEGER)) / 365.25) AS Age, *
from users) as users
WHERE Age >= 10 AND Age < 20
There are number of ways to calculate age.
You can try the following:
SELECT * FROM TableName
WHERE DATEDIFF(year, dob, getdate()) between #dob and #currentDate;
OR
SELECT DATEDIFF(day,'2014-06-05','2014-08-05') AS DiffDate;
Reference: http://www.w3schools.com/sql/func_datediff.asp
OR
http://sqlhints.com/2015/07/10/how-to-get-difference-between-two-dates-in-years-months-and-days-in-sql-server/
Below query should return the users :
SELECT *
from users
where FLOOR ( (CAST (GetDate() AS INTEGER) - CAST(dob AS INTEGER)) / 365.25)
between 10 and 20;
Instead of calculating each users age you might simply change your WHERE-condition to:
where dob between cast(dateadd(year, 20, getdate()) as date)
and cast(dateadd(year, 10, getdate()) as date)
Now it's a sargable expression and might use an index.
I found this question trying to figure out something very similar. I'm really new to SQL and found a discussion about calculating age from date of birth here.
I've adapted one of the answers there into this: I think it works.
SELECT
(0 + Convert(Char(8),GETDATE(),112) - Convert(Char(8),dob,112)) / 10000 AS Age
FROM
users
WHERE
(0 + Convert(Char(8),GETDATE(),112) - Convert(Char(8),dob,112)) / 10000 BETWEEN 10 and 20
;