Calculate the age in Microsoft SQL Server Management Studio - sql

I'm doing this but the result give me all the names who they are 30 years and less than 30 years.
This is the database:
Donor ( Donor-ID, First-name, Last-name, Date-of-birth, Sex, Date-of-donate)
Donor-phone (Donor-ID, Phone-number)
Clinic (Clinic-ID, Clinic-name, Clinic-Location)
Blood (Blood-ID, Blood Type)
The donate day (Blood Status, Donate Date)
Employee (Employee-ID, First-name, Last-name, Sex)
I used this code - where is it wrong?
SELECT
GETDATE () AS FirstName,
FirstName, LastName,
DATEADD(DD, 30, GETDATE()) AS [DateOfDonate- DateOfBirth],
DATEADD(DD, 1-1-2000, GETDATE()) AS [DonateOfDate]
FROM
Donor
I need to solve this question: find the names of donors who their age is above 30 years and have donated since 1/1/2000

SELECT
*
FROM
donor
WHERE
[date-of-birth] <= DATEADD(YEAR, -30, GETDATE()) -- Anyone born more than 30 years ago
AND [date-of-donate] >= '2000-01-01' -- Anyone that donated since 1st Jan 2000

Sorry for the previous typo . I calculated with actual fields and then replaced with yours resulting into the mess.
Please use below
cast(datediff(Year,Date-Of-Birth,getdate()) as nvarchar(100))
+ ' Years , '
+ cast(datediff(Month,Date-Of-Birth,getdate())%12 as nvarchar(100))
+ ' months and '
+ cast(datediff(day,Date-Of-Birth,getdate()) as nvarchar(100))
+' days '

select FirstName+" "+ LastName from Donor
where datediff(year,Date-of-birth,getdate()) >30 and Date-of-donate>
convert(date,'Date-of-donate',103)=convert(date,'Date-of-
donate',103)='1/1/2000'
This will work for you

Related

DateDiff function adding an extra year for the customer dob

How can I alter the SQL query to not return a 3 for customer Mike since he is not 3 years old yet. As you can see the customer turns 3 in December of 2021. But my query is giving him the age of 3. Is there anyways to alter or make a query that gives him the correct age?
SELECT
id,
name,
dob,
DATEDIFF(YYYY, dob, GETDATE())
FROM
customer
WHERE
DATEDIFF(YYYY, dob, GETDATE()) >= 2
AND DATEDIFF(YYYY, dob, GETDATE()) <= 4
Results:
id name dob datediff
-------------------------------
1 Mike 2018-12-05 3
There are many varied solutions to this issue on SQL Server. This answer is based on a Stack Overflow answer from a question where the accepted answer is not the best answer imo. When it comes to calculating "age from birth" there are advantages to using date format 112. You could try calculating the customer age something like this
declare
#as_of datetime=getdate(),
#bday datetime='2018-12-05';
select
(0 + Convert(Char(8),#as_of,112) - Convert(Char(8),#bday,112))/10000 age;
age
2
If you want an integer number of years (no fractional part)...
SELECT
*,
CASE
WHEN DATEADD(year, diff.years, customer.dob) > GETDATE()
THEN diff.years - 1
ELSE diff.years
END
AS age
FROM
customer
CROSS APPLY
(
SELECT DATEDIFF(year, customer.dob, GETDATE()) AS years
)
AS diff
WHERE
customer.dob > DATEADD(year, -5, CAST(GETDATE() AS DATE)) -- Born more recently than 5 years ago, so at most 4 years 11 month and 30 days old
AND customer.dob <= DATEADD(year, -2, CAST(GETDATE() AS DATE)) -- Born two years ago or earlier, so at least 2 years and 0 days old
The cross apply is just so that I can write the DATEDIFF() once and refer to it as many times as I like (Don't Repeat Yourself).
But then I also refactored the where clause. By moving the calculation to be on GETDATE() rather than on the dob column, I both make the maths simpler (than the case statement), but also make it so that any index on dob can be used (SARGable).
CAST(GETDATE() AS DATE) just removes the time part of today's date, on the assumption your dob (and calculations) don't account for the exact time they were born ;)

How to find the minimum age from birthday column, but the select only those that are 3 years older than minimum

I have a table, PATIENT, that has birth dates. I need to run a query that returns only those patients that are 3 years older than the youngest.
I am trying to find a good intro tutorial on nested sql statements because my online class is terrible.
This is as far as I've got:
SELECT Phone, Birthday
FROM PATIENT
WHERE Birthday >(
SELECT *
FROM PATIENT
GROUP BY Birthday
ORDER BY Birthday DESC
SELECT MIN(Birthday) AS MinAges
FROM PATIENT);
Don't google for "nested" that is a different thing. Google "subqueries".
SELECT Phone, Birthday
FROM PATIENT
WHERE Birthday - 2 > (
SELECT MIN(Birthday)
FROM PATIENT
);
Here we select those two fields from patient where the birthday is greater then a nested select where we take the least recent birthday and add 3 years to it. Hopefully this points you in the right direction.
SELECT Phone, Birthday
FROM PATIENT
WHERE Birthday >(
SELECT DateAdd(yy, 3, Cast(MIN(Birthday) As datetime))
FROM PATIENT);
If by 3 years older you mean that you want the years of the birthday have a difference of 3 then you can use the DateAdd() function:
select phone, birthday from patient
where year(DateAdd('yyyy', -3, birthday)) = (
select year(min(birthday))
from patient
)
or
select phone, birthday from patient
where year(birthday) - 3 = (
select year(min(birthday))
from patient
)
You can use a subquery to get the oldest birthdate and then date comparisons. This looks like:
select p.*
from patient as p,
(select max(birthday) as max_birthday
from patient
) as m
where p.birthday <= dateadd("yyyy", -3, m.max_birthday) and
p.birthday > dateadd("yyyy", -4, m.max_birthday);
Note that this is precisely 3 years, based on the day of the your

sql for getting the total difference of two dates in same format

I want to write a query in sql for find the age of a person in day month and year .....lik3
Age:'65Years/7Month/2Days'
I have a table consist the name and the date of birth of employee
I am able to find the age in year or month or day by using datediff query but donno how to write for mixup of all
DATEDIFF(day,Column_1,DateNow())
try this:
CREATE TABLE emp(ename varchar(100),DOB date, Age varchar(100))
INSERT INTO emp
VALUES('d','06/02/2011',NULL)--,('b','07/10/1947',NULL),('c','12/21/1982',NULL)
;WITH CTE(ename,DOB,years,months,days)
AS
(
SELECT
ename,DOB,DATEDIFF(yy,DOB,getdate()),DATEDIFF(mm,DOB,getdate()),DATEDIFF(dd,DOB,getdate())
FROM
emp
)
SELECT
ename,DOB,CAST(months/12 as varchar(5))+' Years'+
CAST((months % 12) as varchar(5))+' month/s '+
CAST(CASE WHEN DATEADD(MM,(months % 12),DATEADD(YY,(months/12),DOB)) <= GETDATE() then
DATEDIFF(dd,DATEADD(MM,(months % 12),DATEADD(YY,(months/12),DOB)),GETDATE())
ELSE DAY(getdate())
END
as varchar(5))+' days' as Age
FROM CTE
Try here http://social.msdn.microsoft.com/Forums/en/transactsql/thread/399a7e87-bc78-47a5-8cc2-2d2436886fd7 google is your friend "ms sql for age from date"
See the method shown here http://www.sqlservercurry.com/2010/07/calculate-age-from-date-of-birth-using.html

How to select one's name day from first name and birth date?

Hey there. I would really appreciate your help in creating a query that would accomplish the following. The problem is with dynamically getting upcoming what we call "namedays" in europe. Nameday is a tradition in many countries in Europe and Latin America of celebrating on a particular day of the year associated with the one's given name (http://en.wikipedia.org/wiki/Name_day).
What i have is a table of all names and their corresponding date (i store the date in this format "1900-08-22", but we really need month & day)
nameday table:
name date
----------------
Bob 1900-04-22
Bob 1900-09-04
Frank 1900-01-02
...
The trick is that there might be multiple entries for each name, and someones "nameday" is always first found after ones birthday. So say Bob #1 was born on August 5th, his nameday would fall on September 4th, but if we was born after Sept 4th his nameday would be on April 22nd.
Obviously i have a table with my users
user table:
id first_name birth_date
------------------------------------
1 Bob 1975-08-05
2 Frank 1987-01-01
...
So, eveything is based on the birthdate, we need to find when a given person celebrates his/her "nameday" based on the first_name and birthdate. When i need to have is a SQL server query that will be able to get me namedays for the people in my database ;)
If you think it would be easier to split the dates in the "nameday" table into: month & day let me know, we can do that. I need to be able to come up with the most efficient solution for this.
Any help is greatly appreciated,
Wojo
I'd recommend you to keep your dates 1904-based, since 1900 was not a leap year and lacked Feb 29th.
However, here's the query with your data:
WITH users AS
(
SELECT 1 AS id, 'Bob' AS first_name, CAST('1975-08-05' AS DATETIME) AS birth_date
UNION ALL
SELECT 2 AS id, 'Frank' AS first_name, CAST('1987-01-01' AS DATETIME) AS birth_date
),
namedays AS
(
SELECT 'Bob' AS name, CAST('1900-04-22' AS DATETIME) AS date
UNION ALL
SELECT 'Bob' AS name, CAST('1900-09-04' AS DATETIME) AS date
UNION ALL
SELECT 'Frank' AS name, CAST('1900-01-02' AS DATETIME) AS date
)
SELECT *
FROM users u
OUTER APPLY
(
SELECT COALESCE(
(
SELECT TOP 1 date
FROM namedays nd
WHERE nd.name = u.first_name
AND nd.date >= DATEADD(year, 1900 - YEAR(u.birth_date), birth_date)
ORDER BY
nd.date
),
(
SELECT TOP 1 date
FROM namedays nd
WHERE nd.name = u.first_name
ORDER BY
nd.date
)
) AS date
) dates
See this post in my blog for performance details:
SQL Server: finding date closest to a birthdate
This seems to be a simple solution:
select u.id, u.first_name, min(isnull(n.date, n2.date)) as nameday
from users u
left join namedays n on u.first_name = n.name and dateadd(year, year(u.birth_date) - 1900, n.date) > u.birth_date
left join namedays n2 on u.first_name = n2.name and dateadd(year, year(u.birth_date) - 1899, n2.date) > u.birth_date
group by u.id, u.first_name
Explanation:
Join the users table with the namedays table (adjusting the namedays.date column to the same year as the birthday). If there is an adjusted date that is after their birthday, this date is used.
If not, the users table is joined with the namedays table again, this time adjusting the date column to the year after the birthday, and use the minimum date that is after their birthday.
This solution returns the correct dates according to your example data, and the situations listed in the problem (Bob's birthday changed to after 9/4 returns Bob's nameday as 4/22).
Here you go:
WITH "nameday_long" ("name", "date", "p_month_day") AS (
SELECT n."name",
n."date",
DATEPART(month, n."date") * 100 + DATEPART(day, n."date")
FROM "nameday" n
UNION ALL
SELECT n."name",
n."date",
DATEPART(month, n."date") * 100 + DATEPART(day, n."date") + 10000
FROM "nameday" n
)
SELECT u."id",
u."first_name",
u."birth_date",
n."date" AS nameday
FROM "user" u
LEFT JOIN "nameday_long" n
ON u."first_name" = n."name"
AND n."p_month_day" = (SELECT MIN(x."p_month_day") FROM "nameday_long" x WHERE x."p_month_day" > DATEPART(month, u."birth_date") * 100 + DATEPART(day, u."birth_date"))
The trick is:
convert dates to the format that does not have years and it easy to compare. I have chosen integer that would be like MMDD representation of the month-day parts of day.
I would even suggest to add a (persistent) computed column to "nameday" table with this formula, but it should not be heavy on computation anyway
extend those namedays to cover 2 years so that it would be easy to find the first one if the persons' nameday is before its birthday (calendar-wise). In this trick I have added 1000 to the MMDD numeric representation to keep natural sort
for each person select the first nameday that comes after his/her birthday month-date
use LEFT JOIN so that people with cool names like "Wojo" would still be shown in the result list even if they do not have a nameday, do they? :)
SELECT Min(nameday.[date]), [user].first_name
FROM nameday
INNER JOIN [user] on nameday.name = [user].first_name
WHERE nameday.[date] >= DateAdd(year, -(DatePart(yyyy, birth_date)-1900), birth_date)
GROUP BY [user].first_name
SELECT user.id, First_name, MIN(nameday.date)
FROM user
INNER JOIN nameday ON user.id = nameday.userid
WHERE user.birth_date < DateAdd(year, YEAR(u.birth_date) - year(nameday.date), nameday.date)
GROUP BY user.id, first_name
WITH namedays AS (
SELECT UPPER(nd.name),
nd.date,
MONTH(nd.date) 'month',
DAY(nd.date) 'day'
FROM NAMEDAYS nd)
birthdays AS (
SELECT u.id,
UPPER(u.first_name) 'first_name',
MONTH(u.birth_date) 'month',
DAY(u.birth_date) 'day'
FROM USERS u)
SELECT t.id,
t.first_name,
MIN(nd.date) 'name_day'
FROM USERS t
JOIN birthdays bd ON bd.id = t.id
JOIN namedays nd ON nd.month >= bd.month AND nd.day >= bd.day AND nd.name = bd.firstname
GROUP BY t.id, t.first_name
DatePart(DayOfYear) is a nice way to compare the dates. And who knew I'd ever learn something culturally new from SO? :-)
declare #nameday table
(
Name varchar(30),
Date smalldatetime
)
declare #user table
(
UserName varchar(30),
Birthday smalldatetime
)
insert into #nameday
select 'Bob', '1900-04-22' union
select 'Bob', '1900-09-04' union
select 'Frank', '1900-01-02'
insert into #user
select 'Bob', '1975-08-05' union
select 'Frank', '1987-01-01'
select UserName,
NameDayDate = Date
from #user as u
inner join #nameday as nd
on nd.Name = u.UserName
and datepart(dayofyear, nd.Date) >= datepart(dayofyear, u.Birthday)
and not exists (select *
from #nameday as ndOlder
where ndOlder.Name = nd.Name
and datepart(dayofyear, ndOlder.Date) >= datepart(dayofyear, u.Birthday)
and ndOlder.Date < nd.Date)

Monthly Birthday SQL Query

How would retrieve all customer's birthdays for a given month in SQL? What about MySQL?
I was thinking of using the following with SQL server.
select c.name
from cust c
where datename(m,c.birthdate) = datename(m,#suppliedDate)
order by c.name
don't forget the 29th February...
SELECT c.name
FROM cust c
WHERE (
MONTH(c.birthdate) = MONTH(#suppliedDate)
AND DAY(c.birthdate) = DAY(#suppliedDate)
) OR (
MONTH(c.birthdate) = 2 AND DAY(c.birthdate) = 29
AND MONTH(#suppliedDate) = 3 AND DAY(#suppliedDate) = 1
AND (YEAR(#suppliedDate) % 4 = 0) AND ((YEAR(#suppliedDate) % 100 != 0) OR (YEAR(#suppliedDate) % 400 = 0))
)
Personally I would use DATEPART instead of DATENAME as DATENAME is open to interpretation depending on locale.
If you're asking for all birthdays in a given month, then you should supply the month, not a date:
SELECT c.name
FROM cust c
WHERE datepart(m,c.birthdate) = #SuppliedMonth
I'd actually be tempted to add a birthmonth column, if you expect the list of customers to get very large. So far, the queries I've seen (including the example) will require a full table scan, as you're passing the the data column to a function and comparing that. If the table is of any size, this could take a fair amount of time since no index is going to be able to help.
So, I'd add the birthmonth column (indexed) and just do (with possible MySQLisms):
SELECT name
FROM cust
WHERE birthmonth = MONTH(NOW())
ORDER BY name;
Of course, it should be easy to set the birthmonth column either with a trigger or with your client code.
SELECT * FROM tbl_Employee WHERE DATEADD( Year, DATEPART( Year, GETDATE()) - DATEPART( Year, DOB), DOB) BETWEEN CONVERT( DATE, GETDATE()) AND CONVERT( DATE, GETDATE() + 30)
This can be use to get the upcoming Birthday by days