简体   繁体   English

MySQL将多行的选定列合并为一

[英]MySQL Combining selected columns of multiple rows into one

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 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.基于我对您上一个问题的回答,我们可以使用此 q/a 中描述的方法使查询动态化,以便处理未知数量的宗教。

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;

Sample SQL Fiddle示例 SQL 小提琴

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:我想您应该生成一个中间查询,然后使用 Pivot 函数将描述转换为多列:

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: Wich 为您提供以下输出:

+-----+------------------+
| 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.然后使用 Pivot、Excel 或其他一些工具将其转换为所需的输出。 I do not know if this can be done in MySQL directly but there are multiple SO Questsions about this.我不知道这是否可以直接在 MySQL 中完成,但是有多个关于此的 SO Questsions。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM