Calculate and create categories age display sum by column - mysql

Here is my query.
I calculate age, after i sum occurence for each categorie everything right.
SELECT
SUM(CASE WHEN AGE <18 THEN 1 ELSE 0 END) AS '<18',
SUM(CASE WHEN AGE >= 18 AND AGE <= 24 THEN 1 ELSE 0 END) AS '18-24',
SUM(CASE WHEN AGE >= 25 AND AGE <= 34 THEN 1 ELSE 0 END) AS '25-34',
SUM(CASE WHEN AGE >= 35 AND AGE <= 44 THEN 1 ELSE 0 END) AS '35-44',
SUM(CASE WHEN AGE >= 45 AND AGE <= 54 THEN 1 ELSE 0 END) AS '45-54',
SUM(CASE WHEN AGE >= 55 THEN 1 ELSE 0 END)AS '>=55'
FROM (SELECT t_personne.pers_date_naissance, t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription) -
CASE WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0 END AS AGE
FROM t_personne) AS Total
give :
<18|18-24|25-34|35-44|45-54|>=55
67 |693 |1619 |1486 |616 |93
But I'd like this:
AGE |Total|
<18 |67 |
18-24|693 |
25-34|1619 |
35-44|1486 |
45-54|616 |
>=55 |93 |

you can use a cross join with the column name to transpose it
SELECT
age_range,
CASE age_range
WHEN '<18' THEN SUM(CASE WHEN AGE <18 THEN 1 ELSE 0 END)
WHEN '18-24' THEN SUM(CASE WHEN AGE >= 18 AND AGE <= 24 THEN 1 ELSE 0 END)
WHEN '25-34' THEN SUM(CASE WHEN AGE >= 25 AND AGE <= 34 THEN 1 ELSE 0 END)
WHEN '35-44' THEN SUM(CASE WHEN AGE >= 35 AND AGE <= 44 THEN 1 ELSE 0 END)
WHEN '45-54' THEN SUM(CASE WHEN AGE >= 45 AND AGE <= 54 THEN 1 ELSE 0 END)
WHEN '>=55' THEN SUM(CASE WHEN AGE >= 55 THEN 1 ELSE 0 END)
END value
FROM
( SELECT
t_personne.pers_date_naissance,
t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription)
- CASE
WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0
END AS AGE
FROM t_personne
) AS Total
CROSS JOIN
( SELECT '<18' age_range UNION ALL
SELECT '18-24' UNION ALL
SELECT '25-34' UNION ALL
SELECT '35-44' UNION ALL
SELECT '45-54' UNION ALL
SELECT '>=55'
)a
GROUP BY age_range
ORDER BY FIELD(age_range, '<18', '18-24', '25-34', '35-44', '45-54', '>=55')
FIDDLE DEMO

Not so elegant but it will work
SELECT
'<18' as AGE,COUNT(AGE) AS Total FROM
(SELECT t_personne.pers_date_naissance, t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription) -
CASE WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0 END AS AGE
FROM t_personne) as Totals where AGE <18
UNION
SELECT
'18-24',COUNT(AGE) AS Total FROM
(SELECT t_personne.pers_date_naissance, t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription) -
CASE WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0 END AS AGE
FROM t_personne) as Totals where AGE >= 18 AND AGE <= 24
UNION
SELECT
'25-34',COUNT(AGE) AS Total FROM
(SELECT t_personne.pers_date_naissance, t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription) -
CASE WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0 END AS AGE
FROM t_personne) as Totals where AGE >= 25 AND AGE <= 34
UNION
SELECT
'35-44',COUNT(AGE) AS Total FROM
(SELECT t_personne.pers_date_naissance, t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription) -
CASE WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0 END AS AGE
FROM t_personne) as Totals where AGE >= 35 AND AGE <= 44
UNION
SELECT
'45-54',COUNT(AGE) AS Total FROM
(SELECT t_personne.pers_date_naissance, t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription) -
CASE WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0 END AS AGE
FROM t_personne) as Totals where AGE >= 45 AND AGE <= 54
UNION
SELECT
'>=55',COUNT(AGE) AS Total FROM
(SELECT t_personne.pers_date_naissance, t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription) -
CASE WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0 END AS AGE
FROM t_personne) as Totals where AGE >= 55

Related

How to change result SQL syntax for age group from colomn to new row

I Tried to grouping age from and found this answer(SQL Group by Age Range)
But the result is as a colomn not a row Like this
I Just want to convert the colomn into a row Like This
The query is:
SELECT SUM(CASE WHEN DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(),user_detail.tanggal_lahir)), '%Y') < 18 THEN 1 ELSE 0 END) AS '< 18',
SUM(CASE WHEN DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(),user_detail.tanggal_lahir)), '%Y') BETWEEN 18 AND 25 THEN 1 ELSE 0 END) AS '18-25 Tahun',
SUM(CASE WHEN DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(),user_detail.tanggal_lahir)), '%Y') BETWEEN 26 AND 35 THEN 1 ELSE 0 END) AS '26-35 Tahun',
SUM(CASE WHEN DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(),user_detail.tanggal_lahir)), '%Y') BETWEEN 36 AND 45 THEN 1 ELSE 0 END) AS '36-45 Tahun',
SUM(CASE WHEN DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(),user_detail.tanggal_lahir)), '%Y') BETWEEN 46 AND 55 THEN 1 ELSE 0 END) AS '46-55 Tahun',
SUM(CASE WHEN DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(),user_detail.tanggal_lahir)), '%Y') BETWEEN 56 AND 65 THEN 1 ELSE 0 END) AS '56-65 Tahun',
SUM(CASE WHEN DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(),user_detail.tanggal_lahir)), '%Y') BETWEEN 66 AND 200 THEN 1 ELSE 0 END) AS '>66 Tahun'
FROM user_detail
My table for tanggal_lahir:

MySQL row count with different age ranges

I have a MySQL table as follows.
emp_no emp_name dob gender
1 A 1978-10-10 Male
2 B 1985-02-20 Female
3 C 1982-04-16 Female
4 D 1980-06-27 Male
Then I need to get the following result.
age_group No of Male No of Female Total
<25 1 0 1
25-35 0 1 1
35-50 0 1 1
>50 1 0 1
I used the following query to get this output.
SELECT TIMESTAMPDIFF(YEAR, dob, NOW()) AS age_group,
COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) <25, 1, 0 ) ) AS ag_C,
COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) BETWEEN 25 AND 35 , 1, 0 ) ) AS ag_B,
COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) BETWEEN 35 AND 50 , 1, 0 ) ) AS ag_C,
COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) >50, 1, 0 ) ) AS ag_D
FROM emp GROUP BY age_group
But I can not get the desired out put. Can anyone help me on this issue ?
try this
SELECT Case
when TIMESTAMPDIFF(YEAR, dob, NOW()) < 25 then '<25'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 25 and 35 then '25-35'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 36 and 50 then '36-50'
else '>50' END AS age_group,
sum(if(gender='Male', 1, 0)) as Male,
sum(if(gender='Female', 1, 0)) as Female,
COUNT(1) as total FROM emp
GROUP BY Case
when TIMESTAMPDIFF(YEAR, dob, NOW()) < 25 then '<25'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 25 and 35 then '25-35'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 36 and 50 then '36-50'
else '>50' END;
Try below:
SELECT Case
when TIMESTAMPDIFF(YEAR, dob, NOW()) < 25 then '<25'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 25 and 35 then '25-35'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 36 and 50 then '36-50'
else '>50' END AS age_group,
sum(case when gender='Male' then 1 end) as Male,
sum(case when gender='Female' then 1 end) as Female,
sum(case when gender in ('Male','Female') then 1 end) as total,
GROUP BY Case
when TIMESTAMPDIFF(YEAR, dob, NOW()) < 25 then '<25'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 25 and 35 then '25-35'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 36 and 50 then '36-50'
else '>50' END
You could try this:
select emp_no,
emp_name,
dob,
gender,
case when age < 25 then 1 else 0 end `<25`,
case when age >= 25 and age < 35 then 1 else 0 end `25-35`,
case when age >= 35 and age < 50 then 1 else 0 end `35-50`,
case when age >= 50 then 1 else 0 end `>=50`
from (
select emp_no,
emp_name,
dob,
gender,
year(now()) - year(dob) - (date_format(now(), '%m%d') < date_format(dob, '%m%d'))
age
from tbl
) a
use case when and sub-query
select
case when age_group < 25 then '<25',
case when age_group >= 25 and age_group < 35 then '25-35',
case when age_group >= 35 and age_group < 50 then '35-50',
case when age_group >= 50 then '>=50' else null end as age_grp,
sum(case when gender='Male' then 1 end) as Male,
sum(case when gender='Female' then 1 end) as Female,
sum(case when gender in ('Male','Female') then 1 else 0 end)
as total from
(
SELECT TIMESTAMPDIFF(YEAR, dob, NOW()) AS age_group,gender
FROM emp
) as t group by age_grp

Calculate percentage and total after create categories mysql

I've this query
SELECT
trage,
CASE trage
WHEN '<18' THEN SUM(CASE WHEN AGE <18 THEN 1 ELSE 0 END)
WHEN '18-24' THEN SUM(CASE WHEN AGE >= 18 AND AGE <= 24 THEN 1 ELSE 0 END)
WHEN '25-34' THEN SUM(CASE WHEN AGE >= 25 AND AGE <= 34 THEN 1 ELSE 0 END)
WHEN '35-44' THEN SUM(CASE WHEN AGE >= 35 AND AGE <= 44 THEN 1 ELSE 0 END)
WHEN '45-54' THEN SUM(CASE WHEN AGE >= 45 AND AGE <= 54 THEN 1 ELSE 0 END)
WHEN '>=55' THEN SUM(CASE WHEN AGE >= 55 THEN 1 ELSE 0 END)
END Total
FROM
( SELECT
t_personne.pers_date_naissance,
t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription)
- CASE
WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0
END AS AGE
FROM t_personne
) AS Total
CROSS JOIN
( SELECT '<18' trage UNION ALL
SELECT '18-24' UNION ALL
SELECT '25-34' UNION ALL
SELECT '35-44' UNION ALL
SELECT '45-54' UNION ALL
SELECT '>=55'
)a
GROUP BY trage
ORDER BY FIELD(trage, '<18', '18-24', '25-34', '35-44', '45-54', '>=55')
it give a table with two columns trage and Total for all categories
How to add a column percentage with a line TOTAL for the column Total and %
Thanks for your help
For the time being, you can't do this. To support this MySQL needs Window Function support which it still doesn't have. If you need functions like these I would recommend switching to PostgreSQL.
Also take a look at this question: MySql using correct syntax for the over clause

Count records for each age range

I have a mysql table
TABLE name test
Id INT PRIMARY KEY
Lahir Date
Gender CHAR(1)
Nama Varchar(100)
id_desa CHAR(4)
How can I get report like this?
id_desa 0-10 11-20 21-30 31-40 41-50
10B 1 2 0 1 8
10C 2 4 7 1 0.
try
select
id_desa,
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 0 and 10 then 1 else 0 end) as '0-10',
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 11 and 20 then 1 else 0 end) as '11-20',
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 21 and 30 then 1 else 0 end) as '21-30',
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 31 and 40 then 1 else 0 end) as '31-40',
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 41 and 50 then 1 else 0 end) as '41-50'
from tbl
You can try to use this query.
I assume that the table name is name_test.
SELECT id_desa,
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 0 AND 10) as "0-10",
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 11 AND 20) as "11-20",
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 21 AND 30) as "21-30",
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 31 AND 40) as "31-40",
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 41 AND 50) as "41-50"
FROM name_test
MySQL has a very nice function called TIMESTAMPDIFF
SELECT
id_desa,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 0 AND 10) `0-10`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 11 AND 20) `11-20`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 21 AND 30) `21-30`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 31 AND 40) `31-40`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 41 AND 50) `41-50`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) > 50) `50+`
FROM tablename
GROUP BY id_desa

MySQL count listing between certain price range

From another post on the site, I took the following type of query. They were using sum, I am looking for a count of listings.
SELECT
COUNT(IF(sold_price < 20,1,0)) as 'Under 20',
COUNT(IF(sold_price BETWEEN 20 and 50,1,0)) as '20 - 50',
COUNT(IF(sold_price BETWEEN 50 and 100,1,0)) as '50 - 100',
COUNT(IF(sold_price BETWEEN 100 and 250,1,0)) as '100 - 250',
COUNT(IF(sold_price BETWEEN 250 and 500,1,0)) as '250 - 500',
COUNT(IF(sold_price BETWEEN 500 and 1000,1,0)) as '500 - 1000',
COUNT(IF(sold_price BETWEEN 1000 and 2000,1,0)) as '1000 - 2000',
COUNT(IF(sold_price > 2000,1,0)) as 'Over 2000'
FROM listings
where current_batch = 'Y'
All my results are coming back as the same number
Under 20 20 - 50 50 - 100 100 - 250 250 - 500 500 - 1000 1000 - 2000 Over 2000
94665 94665 94665 94665 94665 94665 94665 94665
Does anyone have any suggestion on show to do this or if this can be done with count?
MySQL documentation says the following(http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_count):
COUNT(expr)
Returns a count of the number of non-NULL values of expr in the rows retrieved by a SELECT statement
So replace:
IF(sold_price BETWEEN 20 and 50,1,0)
by
IF(sold_price BETWEEN 20 and 50,1,NULL)
Use SUM instead of COUNT in your query like:
SELECT
SUM(CASE WHEN our_price <= 10000 THEN 1 ELSE 0 END) AS p10000,
SUM(CASE WHEN our_price >= 10001 AND our_price <= 25000 THEN 1 ELSE 0 END) AS p25000,
SUM(CASE WHEN our_price >= 25001 AND our_price <= 50000 THEN 1 ELSE 0 END) AS p50000,
SUM(CASE WHEN our_price >= 50001 AND our_price <= 75000 THEN 1 ELSE 0 END) AS p75000,
SUM(CASE WHEN our_price >= 75001 AND our_price <= 100000 THEN 1 ELSE 0 END) AS p100000,
SUM(CASE WHEN our_price >= 100001 AND our_price <= 150000 THEN 1 ELSE 0 END) AS p150000,
SUM(CASE WHEN our_price >= 151000 AND our_price <= 200000 THEN 1 ELSE 0 END) AS p200000,
SUM(CASE WHEN our_price > 200000 THEN 1 ELSE 0 END) AS p200001
FROM products;