I want to count the number of male & female user of each religion of each age to obtain a resulting table like the third table below.
I have two tables as below:
tbl_user
+----+----------+------------+--------+-----------+
| id | name | dob | gender | religion |
+----+----------+------------+--------+-----------+
| 1 | raj | 1999-12-21 | m | 1 |
| 7 | raju | 1998-10-10 | m | 2 |
| 8 | rajan | 2000-11-23 | m | 3 |
| 11 | neetu | 1992-12-06 | f | 1 |
| 12 | sita | 1993-06-16 | f | 2 |
| 13 | rita | 1992-06-08 | f | 3 |
| 14 | jenny | 1993-05-10 | f | 2 |
| 15 | manju | 1993-12-16 | f | 1 |
| 16 | aanju | 1993-03-05 | f | 3 |
| 17 | raja | 1995-04-06 | m | 1 |
| 18 | rajendra | 1995-07-03 | m | 2 |
| 19 | rajesh | 1991-05-02 | m | 3 |
+----+----------+------------+--------+-----------+
tbl_religion
+----+-----------+
| id | name |
+----+-----------+
| 1 | Christian |
| 2 | Hindu |
| 3 | Islam |
+----+-----------+
The religion table can have any number of records(religions).
Now I want to count the number of male & female user of each religion of each age to obtain a resulting table like the one below. The user can be of any age or or born on any year:
+-----+----------------+------------------+------------+--------------+------------+--------------+
| Age | Christian Male | Christian Female | Hindu Male | Hindu Female | Islam Male | Islam Female |
+-----+----------------+------------------+------------+--------------+------------+--------------+
| 14 | 0 | 0 | 0 | 0 | 1 | 0 |
| 15 | 1 | 0 | 0 | 0 | 0 | 0 |
| 16 | 0 | 0 | 1 | 0 | 0 | 0 |
| 20 | 1 | 0 | 1 | 0 | 0 | 0 |
| 21 | 0 | 1 | 0 | 0 | 0 | 0 |
| 22 | 0 | 1 | 0 | 2 | 0 | 1 |
| 23 | 0 | 0 | 0 | 0 | 1 | 1 |
| 24 | 0 | 0 | 0 | 0 | 0 | 0 |
+-----+----------------+------------------+------------+--------------+------------+--------------+
Thank you for any help.
Building on my answer to your previous question , we can use the method described in this q/a to make the query dynamic so that it handles an unknown number of religions.
The final query will look like this:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(gender = ''', gender,
''' and r.name = ''',
r.name, ''') AS "',
if(gender='m','Male','Female'),
' ', r.name, '" '
)
) INTO @sql
FROM
tbl_user u
JOIN
tbl_religion r ON u.religion = r.id;
SET @sql = CONCAT(
'select timestampdiff(year, dob, now()) age, ', @sql, '
from tbl_user u
join tbl_religion r on u.religion = r.id
group by timestampdiff(year, dob, now());');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
You could select the columns by hand:
SELECT
TIMESTAMPDIFF(YEAR, u.dob, CURRENT_DATE) AS 'Age',
SUM(CASE
WHEN r.name = 'Christian' AND u.gender = 'm' THEN 1
ELSE 0
END) AS 'Christian Male',
SUM(CASE
WHEN r.name = 'Christian' AND u.gender = 'f' THEN 1
ELSE 0
END) AS 'Christian Female'
FROM tbl_user u
LEFT JOIN tbl_religion r ON r.id = u.religion
But then you would need to change your query for each new religion. I suppose you should generate an intermediate query and use a Pivot Function to transpose the Description into multiple columns later:
SELECT
TIMESTAMPDIFF(YEAR, u.dob, CURRENT_DATE) AS 'Age',
CONCAT(r.name, ' ', CASE
WHEN u.gender = 'm' THEN 'Male'
WHEN u.gender = 'f' THEN 'Female'
ELSE 'Unknown'
END) AS 'Description'
FROM tbl_user u
LEFT JOIN tbl_religion r ON r.id = u.religion
Wich gives you the following output:
+-----+------------------+
| Age | Description |
+-----+------------------+
| 14 | Christian Male |
| 15 | Christian Female |
| 16 | Hindu Male |
| 20 | Hindu Female |
| 21 | Islam Male |
+-----+------------------+
Then you turn it into your desired output using Pivot, using Excel or some other tool. I do not know if this can be done in MySQL directly but there are multiple SO Questsions about this.
For the first two tables
select count(a.id) as 'Population',
timestampdiff(year,a.dob,current_date)as 'Age',
b.name as 'Religion'
from tbl_user a
inner join tbl_religion b on a.ethnicity=b.name
group by
timestampdiff(year,a.dob,current_date),
b.name
for the third table
select sum(Christian_Male)+sum(Christian_Female)as 'Christian',
sum(Hindu_Male)+sum(Hindu_Female)as 'Hindu',
sum(Islam_Male)+sum(Islam_Female)as 'Islam',
Age
from religion_table
group by
Age
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.