MariaDB:Select 每个项目每月平均(数据透视 table)

MariaDB: Select average per month per item (Pivot table)

我的 MariaDB table 看起来像这样:

Component Timestamp Duration
Component one 2021-10-01 14:04:54 40
Component one 2021-11-01 14:04:45 10
Component one 2021-11-11 11:05:23 20
Component one 2021-12-01 13:04:43 20
Component one 2021-12-12 12:14:11 30
Component two 2021-11-01 14:04:27 45
Component two 2021-12-01 13:04:08 23

我想做的是显示过去三个月每个组件的平均持续时间。它应该看起来像这样:

Component AVG Duration (October) AVG Duration (November) AVG Duration (December)
Component one 40 15 25
Component two 45 23

我试着弄乱了我在网上找到的数据透视表 table,但下面的查询仍然会产生多行(每个月 1 行,其他月份在该行上为空)

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
               CONCAT('(IF(MONTHNAME(s.LOG_TIMESTAMP) = "', MONTHNAME(`LOG_TIMESTAMP`),'", AVG(`DURATION`),"")) AS ',MONTHNAME(LOG_TIMESTAMP) )
              ) INTO @sql
FROM table1;


SET @sql = CONCAT('SELECT s.COMPONENT,  ', @sql, ' 
                  FROM table1 s
                 GROUP BY s.COMPONENT, MONTHNAME(s.LOG_TIMESTAMP)
                 ORDER BY s.COMPONENT');
SELECT @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt;

所以如果我 运行 查询组件 1(例如)的输出是这样的:

Component AVG Duration (October) AVG Duration (November) AVG Duration (December)
Component one 40
Component one 15
Component one 25

它可能是具有 log_timestamp 的分组依据表达式,但是如果我删除那个表达式,concat 函数只会写入第一个可用月份的平均持续时间(所有月份)。我没有任何旋转 tables 的经验,所以我在这里有点力不从心。任何帮助将不胜感激。

分两步完成:

  1. 编写一个查询来计算平均值。
  2. 使用 'derived table'.
  3. 中的第 1 步查询,编写数据透视查询

也许最终的查询是这样的:

SELECT Component,
       MAX(IF(mth=10,avgd,0)) AS 'October',
       MAX(IF(mth=11,avgd,0)) AS 'November',
       MAX(IF(mth=12,avgd,0)) AS 'December'
 FROM
(SELECT Component,
       MONTH(LOG_TIMESTAMP) mth,
       AVG(Duration) Avgd
FROM table1
GROUP BY Component, mth) v
GROUP BY Component;

准备语句语法如下:

SET @sql := NULL;

SELECT CONCAT('SELECT Component,',
       GROUP_CONCAT(CONCAT('
       MAX(IF(mth=',mth,',avgd,0)) AS "',mthname,'"') 
       SEPARATOR ','),
       '
FROM (SELECT Component,
       MONTH(LOG_TIMESTAMP) mth,
       AVG(Duration) Avgd
FROM table1
GROUP BY Component, mth) v
GROUP BY Component') INTO @sql
FROM
(SELECT DISTINCT MONTH(LOG_TIMESTAMP) mth, 
       MONTHNAME(LOG_TIMESTAMP) mthname
FROM table1) a;

SELECT @sql;

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Demo fiddle