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

MySQL Combining selected columns of multiple rows into one

我想计算每个年龄段每个宗教的男性和女性用户的数量,以获得结果 table,如下面的第三个 table。

我有两个 table 如下:

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     |
+----+-----------+

宗教 table 可以有任意数量的记录(宗教)。

现在我想计算每个年龄段每个宗教的男性和女性用户数量,以获得如下所示的结果 table。用户可以是任何年龄或出生于任何年份:

+-----+----------------+------------------+------------+--------------+------------+--------------+
| 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 |
+-----+----------------+------------------+------------+--------------+------------+--------------+

感谢您的帮助。

对于前两个 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

第三个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

, we can use the method described in this q/a 的基础上使查询动态化,以便它处理未知数量的宗教。

最终查询将如下所示:

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

您可以手动 select 列:

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

但是您需要针对每个新宗教更改您的查询。我想您应该生成一个中间查询,然后使用数据透视函数将描述转置到多个列中:

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

+-----+------------------+
| Age | Description      |
+-----+------------------+
| 14  | Christian Male   |
| 15  | Christian Female |
| 16  | Hindu Male       |
| 20  | Hindu Female     |
| 21  | Islam Male       |
+-----+------------------+

然后使用 Pivot、Excel 或其他工具将其转换为所需的输出。我不知道这是否可以直接在 MySQL 中完成,但是关于这个有多个 SO 问题。