SQL calculations issue - sql

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.

Related

Calculating age in where clause

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;

SQL Query with date range Male Female

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;

Find and filter to current year employees anniversary date using DATADD and CASE Statement

i am trying to find the employee anniversary dates in increments of 5 year, 10 year 15 yea and so on, which i was able to get results but i am trying to filter the 'Anniversary_Year column created in the case statement to only show results of the current year, no past or future results needed just what is coming up.
SELECT Employee,Hire_Date
CASE
WHEN DATEADD(year, 5, Hire_Date) >= GETDATE()
THEN DATEADD(year, 5, Hire_Date)
ELSE NULL
END AS '5_Year_Anniversary',
CASE
WHEN DATEADD(year, 10, Hire_Date) >= GETDATE()
THEN DATEADD(year, 10, Hire_Date)
ELSE NULL
END AS '10_Year_Anniversary',
CASE
WHEN DATEADD(year, 15, Hire_Date) >= GETDATE()
THEN DATEADD(year, 15, Hire_Date)
ELSE NULL
END AS '15_Year_Anniversary',
CASE
WHEN DATEADD(year, 25, Hire_Date) >= GETDATE()
THEN DATEADD(year, 25, Hire_Date)
ELSE NULL
END AS '25_Year_Anniversary'
FROM
MyTable
WHERE YEAR(Hire_Date) = YEAR(getdate())
Use the WHERE clause to only return even 5 year anniversary rows.
SELECT Employee, Hire_Date,
cast(YEAR(getdate()) - YEAR(Hire_Date) as varchar(5)) + 'anniversary'
FROM MyTable
WHERE (YEAR(getdate()) - YEAR(Hire_Date)) % 5 = 0
and YEAR(getdate()) > YEAR(Hire_Date)

Select statement that gives the names,ages, and counrty of birth when female but needs to give DateOfBirth as an age instead of DOB

So far I have:
Select FullName, DateOfBirth, CountryOfBirth
FROM Students
WHERE Gender = F
however I want the DateOfBirth to be Displayed as an age under an age heading.
Can I use this: (Datediff("yyyy",DateOfBirth,DATE())) if so where in my original statement would it go?
Select FullName, DATEDIFF(year,DateOfBirth,DATE()) , CountryOfBirth FROM Students WHERE Gender = F
You can modify the DATEDIFF function to calculate the age according to the date instead of just the year
You probably don't want to use datediff with yyyy as that won't actually give you the ages correctly. It'll give you the years since the year they were born. If someone has a birthday later in the year than today then they'll be returned as a year older than they are.
What I would do is use datediff with hour or day:
datediff(day, DateOfBirth, DATE()) / 365
or
datediff(hour, DateOfBirth, DATE()) / (24 * 365)
You need a proper method for calculating age - an example is shown here:
https://stackoverflow.com/a/29127001/3527297
Yes, you can use the DateDiff function to achieve this. That function would replace the DateOfBirth column in the query, to become:
SELECT FullName, DATEDIFF(yyyy, DateOfBirth, DATE()) As Age, CountryOfBirth
FROM Students
WHERE Gender = F
Unfortunately, there is some contention around leap years in SQL. There isn't a straightforward way to deal with them. There's an updated statement below, but it awkwardly uses cases:
DECLARE #startDate DATETIME = '1984-01-02'
DECLARE #endDate DATETIME = '2015-01-01'
Select Case
When DatePart ( day, #startDate) <= DatePart (day , #endDate )
Then DateDiff ( year, #startDate, #endDate)
When DateDiff (year , #startDate , DateAdd (year , - 1, #endDate)) = - 1
Then 0
Else DateDiff (year , #startDate , DateAdd (year , - 1, #endDate))
End As DoB
You may want to consider putting this DateOfBirth check into a Function for brevity/re-usability.

sql where clause issue with date older than 5 years

How do I not include people with a birth date older than 5 years from today's date? Here is what I have, I just dont know how to put it in my where clause.
SELECT firstname, lastname, age, gender, birthdate
FROM Person
WHERE ... ... ...
I would use:
dateadd(year,-5, getdate()) >= birthdate
datediff(year,yourdate,getdate()) > 5
The best way to do this is:
where birthdate <= dateadd(year, -5, getdate())
The reason this is "best" is because all the operations are on non-columns values (getdate() rather than birthdate). This allows the engine to take advantage of an index on birthdate when processing this where clause.
Use DATEADD to subtract 5 years from todays date:
SELECT firstname, lastname, age, gender, birthdate
FROM Person
WHERE birthdate < DATEADD(year, -5, GETDATE())