Get the correct days in vacation accumulation report - sql

I need acculate how many days between today and Employee hiredate(but do not care the year). That mearn if one employee hire in 07/1/2012, i want to get a result is today 07/15/2013-07/1/2013, that is 15 days. I do not need the hire year 2012.
i play around with the dateadd and datediff but just did not get the correct result.
SELECT
Co Employee,
LastName,
FirstName,
dateadd(dd, DATEDIFF(dd,CURRENT_TIMESTAMP,0),HireDate)
FROM dbo.PREH

You could use modulus division:
SELECT DATEDIFF(DAY,'20120101',GETDATE())%365
The downside is that you're treating leap year the same as every other year, which you could handle with case logic.
In your code:
SELECT
Co Employee,
LastName,
FirstName,
DATEDIFF(DAY,HireDate,GETDATE())%365 AS DaysThisYear
FROM dbo.PREH

This is a bit brute force, perhaps, but it seems to work. The idea is to add a number of years to the hiredate, then to check that against the current date. When it is greater, use one fewer years:
select (case when DATEADD(year, datediff(year, hiredate, getdate()), hiredate) < GETDATE()
then DATEDIFF(dd, DATEADD(year, datediff(year, hiredate, getdate()), hiredate), getdate())
else DATEDIFF(dd, DATEADD(year, datediff(year, hiredate, getdate()) - 1, hiredate), getdate())
end)
from preh;
The problem is that datediff() with year returns the number of times that the year boundary is crossed, not the number of years between two dates as a span. So, there is one year between 2012-12-30 and 2013-01-01, and there is one year between 2012-01-01 and 2013-12-31.

It sounds like you're dropping the year just as part of formatting the output. Formatting shouldn't affect the underlying data though. The last element of your tuple should be:
datediff(day, HireDate, getdate())
That way you can do arithmetic on the data, and save the formatting for downstream, when it's needed.

Related

Computed Column Date Leap Year issue

I have a table of names and associated birthdates. I can retrieve the names of everyone whose birthday is today by matching the MONTH and DAY dateparts between the birthdate in the database and the current date. However, I need to pull "looking forward" lists of, say, all birthdays in the next two weeks.
The obvious solution would be a computed column for each person, showing his/her "birthday this year". It's easy to pull the month and day from the birthday, add the current year, and cast the whole string as a date. That way I could just retrieve those whose "birthday this year" is within X days of the current date. However, I have one person with a birthday on February 29, and there isn't a Feb. 29 every year, so the calculated column "chokes" when I query or open the table with the following error:
The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
Suggestions on a way to either make a computed column work properly in this situation, or an alternative way to query using the date of birth in the table?
Change your query from using convert to using try_convert which will not error on nonexistent date but will instead return NULL. This will exclude your Feb 29 birthday client if running year is not leap.
Your approach won't work for the end of December, because the year changes. Here is a different approach:
Add the number of years to the date and let the database handle leap years.
Then do the comparison.
So, the logic for the first is:
select dateadd(year, year(getdate()) - year(dob), dob)
Then to get dates of birth in the next two weeks:
where dateadd(year, year(getdate()) - year(dob), dob) >= convert(date, getdate()) and
dateadd(year, year(getdate()) - year(dob), dob) < dateadd(14, day, convert(date, getdate())
However, this still doesn't handle dates of birth that could be next year. So, to handle the end of year, consider that as well:
where (dateadd(year, year(getdate()) - year(dob), dob) >= convert(date, getdate()) and
dateadd(year, year(getdate()) - year(dob), dob) < dateadd(14, day, convert(date, getdate())
) or
(dateadd(year, 1 + year(getdate()) - year(dob), dob) >= convert(date, getdate()) and
dateadd(year, 1 + year(getdate()) - year(dob), dob) < dateadd(14, day, convert(date, getdate())
)
To do this - you need to calculate the current year's DOB and the persons next date of birth. To calculate the current year date of birth we can use a simple calculation:
dateadd(year, datediff(year, DateOfBirth, CurrentDate), DateOfBirth)
Then - we need to calculate the next date of birth, which is simply adding a year if the current year DOB is less than CurrentDate:
dateadd(year, iif(CurrentDOB < CurrentDate, 1, 0), CurrentDOB)
Now - it is just a matter of checking if the next DOB is in the range. Here is some sample data to show how to put this together.
--==== Some sample dates of birth - including leap year DOB's
Declare #testData Table (DateOfBirth date);
Insert Into #testData (DateOfBirth)
Values ('1992-01-09'), ('2020-02-29'), ('1965-09-30'), ('1984-02-29');
--==== Test using different dates
Declare #current_date date = '2021-02-28';
--==== Use CROSS APPLY to calculate current year DOB and Next DOB
Select *
From #testData As td
Cross Apply (Values (dateadd(year, datediff(year, td.DateOfBirth, #current_date), td.DateOfBirth))) As y(CurrentDOB)
Cross Apply (Values (dateadd(year, iif(y.CurrentDOB < #current_date, 1, 0), y.CurrentDOB))) As n(NextDOB)
Where n.NextDOB <= dateadd(day, 14, #current_date);
If today is 2021-02-28 then the birthdays that fall on the 29th will be included. If today is 2021-03-01 then those will not be included because they would be calculated as 2022-02-28 which is not within 14 days.

how to get the difference between 2 dates in years and months in same query using sub queries?

I'm using the Northwind DB SQL and trying to get the difference between 2 dates in years with months on it not separate. Example employee hireDate 1992-05-01 should be 27 years 0 months and 1992-08-14 must be 2 years 8 months using today as the date to compare.
I want to get the results for each row of the table with other values in one result example
FirstName| hireDate | hiredYears | hiredMonths
nancy 1992-05-01 6 11
This is my query
SELECT months-(Age*12) FROM (
SELECT CASE WHEN dateadd(year, datediff (year, [HireDate], getdate()),[HireDate]) > getdate()
THEN datediff(year, [HireDate], getdate()) - 1
ELSE datediff(year, [HireDate], getdate())
END as Age,
(case when datepart(day,getdate()) >= datepart(day,[HireDate])
then datediff(month, [HireDate], getdate())
else datediff(month, [HireDate], dateadd(month,-1,getdate()))
end) as months
FROM [Employees]
) results;
The first query gave me the months and the subquery in years but I don't know how to create a subquery that shows everything together. Also, I will like to know if this subquery can have bad performance because I would like to use something similar in a table with a lot of records, any advice or link to read?
I think the right answer is to get the value in months and then do the arithmetic:
SELECT months / 12 as years,
month % 12 as months
FROM employees e CROSS APPLY
(VALUES (DATEDIFF(month, hiredate, getdate())
) v(months);
I think you just need to divide the months by twelve to get the full years and use modulo twelve on them to get the remaining months. Use concat() to compose a string in the form of "n years m months".
SELECT concat(datediff(month, hiredate, getdate()) / 12,
N' years ',
datediff(month, hiredate, getdate()) % 12,
N' months')
FROM employees;
Try this-
SELECT FirstName,
hireDate ,
DATEDIFF(YY,hireDate ,GETDATE()) hiredYears,
DATEDIFF(MM,hireDate ,GETDATE())%12 hiredMonths
FROM your_table

SQL Select query using current date time to get the users ages? [duplicate]

This question already has answers here:
How to calculate age (in years) based on Date of Birth and getDate()
(40 answers)
Closed 7 years ago.
I want to find age, for example, between 20 to 30 from my table from the current system date.
Below is my table details:
GivenName DOB
Raj 1950-06-06 00:00:00.000
Rahul 1951-01-06 00:00:00.000
Mohan 1952-11-09 00:00:00.000
khan 1953-07-24 00:00:00.000
for example, between 20 to 30
Use DATEDIFF:
SELECT Age = DATEDIFF(year, DOB, GetDate()),
Between20_30 = CASE WHEN DATEDIFF(year, DOB, GetDate()) BETWEEN 20 AND 30
Then 'yes' ELSE 'no' END
FROM dbo.Table1
Demo
If you want to filter by persons who are between 20 and 30 use a WHERE clause:
WHERE DATEDIFF(year, DOB, GetDate()) BETWEEN 20 AND 30
Since DATEDIFF ist not precise(treats the month difference between 12/31 and 01/01 as one month), if that's an issue you could use this approach.
select GivenName,Age = DATEDIFF(year, DOB, GetDate())
FROM [dbo].[AgeCalc] where DATEDIFF(year, DOB, GetDate()) BETWEEN 20 AND 30
Don't use DATEDIFF. When using DATEDIFF(year, ...) it is only the year part of the dates that is being considered. So it wouldn't matter which birthday exactly and you'd consider people 20 years old who are not yet full twenty years old.
Today 2015-12-26 you would want persons born between 1984-12-17 till 1995-12-16.
1984-12-17 (today minus 31 years plus one day) means the person gets 31 tomorrow
1995-12-16 (today minus 20 years) means the person just got 20 today.
So:
select *
from persons
where convert(varchar, dob, 102)
between convert(varchar, dateadd(day, 1, dateadd(year, -31, getdate())), 102)
and convert(varchar, dateadd(year, -20, getdate()), 102);
(I must admit though that I am too lazy to think the February 29 thing through now.)

select month and year from Date of birth IN sql

i have table with DOB column ('2012-05-29 00:00:00.000') and few other fields , i need to select the data for DOB between 6 months to 6 Years. I tried using the below SQL but this is not giving me the right data. any help will be appreciated.
select * from dbo.xyz
where ( FLOOR(DATEDIFF(MONTH, birth_date , GETDATE()) % 12) >=6
AND FLOOR(DATEDIFF(DAY, birth_date , GETDATE()) / 365.25) <= 6
)
When using dates, the advice is to use functions only on the non-column values. In other words, modify getdate(), not birth_date:
select *
from dbo.xyz
where birth_date between dateadd(year, -6, getdate()) and dateadd(month, -6, getdate())
This has two advantages. First, it makes the where clause "sargable", which means an index can be used on the comparison. More importantly, the alternative of using datediff() doesn't quite work as expected. datediff() counts the number of calendar boundaries between two values. So, 2014-12-31 and 2015-01-01 are one day apart, one month apart, and even one year apart.
Try this
select * from dbo.xyz
where DATEDIFF(MONTH, birth_date , GETDATE()) between 6 and 72
Here is another option that will allow indexing on birthdate.
select *
from dbo.xyz
where birthdate > DATEADD(YEAR, -6, GETDATE())
and birthdate < DATEADD(MONTH, -6, GETDATE())

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())