Hi i want to select data from table where age between 30-50 from date of birth column.
SELECT * FROM
(SELECT FLOOR((CAST (GetDate() AS INTEGER) - CAST(dob1 AS INTEGER)) / 365.25) AS Age, *
from tbl_travelins) as tbl_travelins
WHERE Age >= 30 AND Age < 50
Try using TIMESTAMPDIFF:
SELECT *
FROM tbl_travelins
WHERE TIMESTAMPDIFF(YEAR, dob1, CURDATE()) BETWEEN 30 AND 49;
Related
I am trying to calculate age based on DOB stored in user table and get result row based on the age.
e.g. I want users whose age between 20 to 30.
I have tried using the sub-query but no luck.
SELECT
id
FROM
personal_info
WHERE
(
SELECT
ROUND(
(
DATEDIFF(
CURRENT_DATE,
STR_TO_DATE(dob, '%Y-%m-%d')
) / 365
)
) AS age
FROM
personal_info
) BETWEEN 20 AND 30
Try below query:
SELECT
id
FROM
personal_info
WHERe
ROUND
(
DATEDIFF(
CURRENT_DATE,
STR_TO_DATE(dob, '%Y-m%-%d')
) / 365
) BETWEEN 20 AND 30
I am trying to create a age group array in mysql.
SELECT
COUNT(*),
CASE
when age < 60 THEN '<60'
when age >= 61 AND age <= 65 then '61-65'
when age >= 66 AND age <= 70 then '66-70'
when age >= 71 AND age <= 75 then '71-75'
when age >= 76 AND age <= 80 then '76-80'
when age > 81 then '>81'
END as age_group
FROM(
SELECT YEAR(current_time()) - Year(DateBorn) AS age
FROM custs
WHERE FDID = 'ANGL01'
) as custs2
GROUP BY age_group
When i ran this query, it worked fine, except that there were 2013 null results. It turns out that there are 2 data formats in the column.
The first on is just the year: 'yyyy'
The second on includes the day and month: 'dd/mm/yyyy'
How can I modify this query to take both data formats into account?
Ideally you should store dates using the DATE data type.
Given your current schema, assuming the dates are always either in yyyy or dd/mm/yyyy format then the year will always be the 4 rightmost characters, so you can use RIGHT(DateBorn,4), like this:
SELECT
COUNT(*),
CASE
when age < 60 THEN '<60'
when age >= 61 AND age <= 65 then '61-65'
when age >= 66 AND age <= 70 then '66-70'
when age >= 71 AND age <= 75 then '71-75'
when age >= 76 AND age <= 80 then '76-80'
when age > 81 then '>81'
END as age_group
FROM(
SELECT YEAR(current_date()) - CAST(RIGHT(DateBorn,4) AS UNSIGNED) AS age
FROM custs
WHERE FDID = 'ANGL01'
) as custs2
GROUP BY age_group
You should check for values that don't match your expected date formats. A query like this will give you a sample of non-conformant rows:
select DateBorn
from custs
where DateBorn not regexp '^[0-9][0-9][0-9][0-9]$'
and DateBorn not regexp '^[0-3][0-9]\/[0-1][0-9]\/[0-9][0-9][0-9][0-9]$'
limit 25
How about MySQL's STR_TO_DATE?
SELECT STR_TO_DATE(DATE_FORMAT(YourField, '%d/%m/%Y'),'%Y')...
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_str-to-date
Using this you can manipulate other occurrences. I have inherited legacy data you cannot change, so this function will accommodate everything you can mask, if your data is fairly consistent.
I may have it backwards. Try this, if needed.
SELECT date_format( str_to_date( dt3, '%m-%d-%Y' ) , '%m/%d/%Y' ) AS my_date FROM dt_tb3
http://www.plus2net.com/sql_tutorial/date-string.php
Assuming that DateBorn is a text column, try this:
SELECT YEAR(now()) - Year(str_to_date(DateBorn,
CASE WHEN char_length(DateBorn) = 4
THEN '01/01/%Y'
ELSE '%d/%m/%Y'
END
)) AS age
current_time() is an alias for curtime() which returns HH:MM:SS. So YEAR(current_time()) may result in some odd results. You might want to try YEAR(NOW()) instead.
You would also want to use STR_TO_DATE(str,format) to parse your varchar as a datetime. (Of course, it is better to fix the schema than patch it like this) Make sure to update the format as you have it in your table.
SELECT
COUNT(*),
CASE
when age < 60 THEN '<60'
when age >= 61 AND age <= 65 then '61-65'
when age >= 66 AND age <= 70 then '66-70'
when age >= 71 AND age <= 75 then '71-75'
when age >= 76 AND age <= 80 then '76-80'
when age > 81 then '>81'
END as age_group
FROM(
SELECT YEAR(NOW()) - Year(str_to_date(DateBorn, '%d/%m/%Y')) AS age
FROM custs
WHERE FDID = 'ANGL01'
) as custs2
GROUP BY age_group
I have an sql table that stores people's details i.e id, name, DoB, registration_date and address. I would like to calculate the age of each individual and then group them into these ranges: 20-30, 31-50, 51 & over.
I know i can get the age by doing: (https://stackoverflow.com/a/1572257/3045800)
SELECT FLOOR((CAST (GetDate() AS INTEGER) - CAST(Date_of_birth AS INTEGER)) / 365.25) AS Age
I just need to figure out how to group all people into thier respective range.
Thanks for the help
Use a case to produce the age group description:
select *,
case
when datediff(now(), date_of_birth) / 365.25 > 50 then '51 & over'
when datediff(now(), date_of_birth) / 365.25 > 30 then '31 - 50'
when datediff(now(), date_of_birth) / 365.25 > 19 then '20 - 30'
else 'under 20'
end as age_group
from person
Note the simpler way to calculate age.
You can use with construction:
with Query as (
select FLOOR((CAST (GetDate() AS INTEGER) - CAST(Date_of_birth AS INTEGER)) / 365.25) AS Age
... -- Other fields
from MyTable
)
select case
-- whatever ranges you want
when (Age < 20) then
1
when (Age >= 20) and (Age <= 30) then
2
when (Age > 30) and (Age <= 50) then
3
else
4
end AgeRange,
...
from Query
group by AgeRange
I was once faced with the same requirement and this is How I fixed it: I wish there was a Straight Forward way as this is Not:
SELECT (CASE
WHEN G.DATE_OF_BIRTH IS NULL
THEN
'18-24' --Put your default Range In case the date of birth is null
ELSE
CASE
WHEN EXTRACT (
YEAR FROM (select sysdate from dual))
- EXTRACT (YEAR FROM g.DATE_OF_BIRTH) < 18
THEN
'MINORS'
ELSE
CASE
WHEN EXTRACT (
YEAR FROM (select sysdate from dual))
- EXTRACT (YEAR FROM g.DATE_OF_BIRTH) BETWEEN 25
AND 29
THEN
'25-29'
ELSE
CASE
WHEN EXTRACT (
YEAR FROM (select sysdate from dual))
- EXTRACT (YEAR FROM g.DATE_OF_BIRTH) BETWEEN 30
AND 34
THEN
'30-34'
ELSE
CASE
WHEN EXTRACT (
YEAR FROM (select sysdate from dual))
- EXTRACT (
YEAR FROM g.DATE_OF_BIRTH) BETWEEN 35
AND 39
THEN
'35-39'
ELSE
CASE
WHEN EXTRACT (
YEAR FROM (select sysdate from dual))
- EXTRACT (
YEAR FROM g.DATE_OF_BIRTH) BETWEEN 40
AND 49
THEN
'40-49'
ELSE
CASE
WHEN EXTRACT (
YEAR FROM (select sysdate from dual))
- EXTRACT (
YEAR FROM g.DATE_OF_BIRTH) BETWEEN 50
AND 59
THEN
'50-59'
ELSE
CASE
WHEN EXTRACT (
YEAR FROM (select sysdate from dual))
- EXTRACT (
YEAR FROM g.DATE_OF_BIRTH) BETWEEN 60
AND 69
THEN
'60-69'
ELSE
CASE
WHEN EXTRACT (
YEAR FROM (select sysdate from dual))
- EXTRACT (
YEAR FROM g.DATE_OF_BIRTH) >=
70
THEN
'ELDERLY'
END
END
END
END
END
END
END
END
END) from your table g
This is just example. Replace the ranges with your Preferred Ones. This I have done using Oracle.
SELECT CASE WHEN age IS NULL THEN 'Unspecified'
WHEN age < 18 THEN '<18'
WHEN age >= 18 AND age <= 24 THEN '18-24'
WHEN age >= 25 AND age <= 30 THEN '25-30'
WHEN age >= 31 AND age <= 40 THEN '31-40'
WHEN age > 40 THEN '>40'
END AS ageband,
COUNT(*)
FROM (SELECT age
FROM table) t
GROUP BY ageband
This is my query. These are the results:
However if the table.age doesn't have at least 1 age in a category, it will just flat out ignore that case in the result. Like such:
This data set didnt have any records for age < 18. So the ageband "<18" doesnt show up. How can I make it so it does show up and return a value 0??
You need a table of agebands to populate the result for entries that have no matching rows. This can be done through an actual table, or dynamically generated with a subquery like this:
SELECT a.ageband, IFNULL(t.agecount, 0)
FROM (
-- ORIGINAL QUERY
SELECT
CASE
WHEN age IS NULL THEN 'Unspecified'
WHEN age < 18 THEN '<18'
WHEN age >= 18 AND age <= 24 THEN '18-24'
WHEN age >= 25 AND age <= 30 THEN '25-30'
WHEN age >= 31 AND age <= 40 THEN '31-40'
WHEN age > 40 THEN '>40'
END AS ageband,
COUNT(*) as agecount
FROM (SELECT age FROM Table1) t
GROUP BY ageband
) t
right join (
-- TABLE OF POSSIBLE AGEBANDS
SELECT 'Unspecified' as ageband union
SELECT '<18' union
SELECT '18-24' union
SELECT '25-30' union
SELECT '31-40' union
SELECT '>40'
) a on t.ageband = a.ageband
Demo: http://www.sqlfiddle.com/#!2/7e2a9/10
I haven't tested it, but this should work.
SELECT ageband, cnt FROM (
SELECT '<18' as ageband, COUNT(*) as cnt FROMT table WHERE age < 18
UNION ALL
SELECT '18-24' as ageband, COUNT(*) as cnt FROMT table WHERE age >= 18 AND age <= 24
UNION ALL
SELECT '25-30' as ageband, COUNT(*) as cnt FROMT table WHERE age >= 25 AND age <= 30
UNION ALL
SELECT '31-40' as ageband, COUNT(*) as cnt FROMT table WHERE age >= 31 AND age <= 40
UNION ALL
SELECT '>40' as ageband, COUNT(*) as cnt FROMT table WHERE age > 40
) as A
Assuming a table AgeCat that contains your categories.
SELECT c.Cat, COUNT(*) FROM Age a
RIGHT JOIN AgeCat c ON (
(a.age < 18 AND c.Cat = '<18')
OR (a.age BETWEEN 18 AND 24 AND c.Cat = '18-24')
OR (a.age BETWEEN 26 AND 30 AND c.Cat = '25-30')
-- etc.
) GROUP BY c.Cat;
This is a follow-up question on Get age from the birthday field with type date using SQL. I have a date field in a MySQL database for the birthday of a user and get the age using this query:
SELECT
ROUND(DATEDIFF(
Cast((SELECT NOW()) as Date),
Cast(birthday as Date)
) / 365, 0) as age
FROM member
Now, I need to select the number of people in different age groups. For example, I need to know how many people are in the age group 13-17, 18-21, 22-25, 26-35, 36-50, 51-MAX.
Is that possible using MySQL?
I have thought of UNIONs, like this:
SELECT
ROUND(DATEDIFF(
Cast((SELECT NOW()) as Date),
Cast(birthday as Date)
) / 365, 0) as age,
1 as agegroup
FROM member WHERE age >=13 AND age <=17
UNION
SELECT
ROUND(DATEDIFF(
Cast((SELECT NOW()) as Date),
Cast(birthday as Date)
) / 365, 0) as age
2 as agegroup
FROM member WHERE age >=18 AND age <=21
But that would be long and ugly. There must be a better way!
select AgeGroup
, count(*)
from (
select case
when age between 13 and 17 then 1
when age between 18 and 21 then 2
...
end as AgeGroup
from (
SELECT ROUND(DATEDIFF(Cast(NOW() as Date),
Cast(birthday as Date)) / 365, 0) as age
FROM YourTable
) as SubQueryAlias
) as SubQueryAlias2
group by
AgeGroup
Another possible solution:-
SELECT AgeRange.MinAge, AgeRange.MaxAge, COUNT(*)
FROM
(
SELECT 13 AS MinAge, 17 AS MaxAge
UNION SELECT 18, 21
UNION SELECT 22, 25
UNION SELECT 26, 35
UNION SELECT 36, 50
UNION SELECT 51, 9999
) AgeRange
INNER JOIN YourTable
ON ROUND(DATEDIFF(CAST(NOW() as DATE), CAST(birthday as DATE)) / 365, 0) BETWEEN AgeRange.MinAge AND AgeRange.MaxAge
GROUP BY AgeRange.MinAge, AgeRange.MaxAge
Possibly easier to expand if needs be, or to move to using date ranges from a table (so the resulting report could be updated by users easily if required).
If you had the age as a column in a table you would do it like this:
SELECT
SUM(CASE WHEN age < 10 THEN 1 ELSE 0 END) AS under10,
SUM(CASE WHEN 10<age AND age <19 THEN 1 ELSE 0 END) AS age10to19,
.
.
.
FROM table
There are likely to be minor changes because age isn't in its own column or if you want extra or different ranges. I'm sure you can work them out yourself!