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 的经验,所以我在这里有点力不从心。任何帮助将不胜感激。
分两步完成:
- 编写一个查询来计算平均值。
- 使用 'derived table'.
中的第 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;
我的 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 的经验,所以我在这里有点力不从心。任何帮助将不胜感激。
分两步完成:
- 编写一个查询来计算平均值。
- 使用 'derived table'. 中的第 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;