I have MariaDB table that looks like this:
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 |
What I'd like to do is show the average duration of each component over the last three months. It should look something like this :
Component | AVG Duration (October) | AVG Duration (November) | AVG Duration (December) |
---|---|---|---|
Component one | 40 | 15 | 25 |
Component two | 45 | 23 |
I tried messing around with a pivot table I found online, but the below query still results in multiple lines (1 for each month, with the other months empty on that line)
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;
So if I run that query the output for component 1 (for example) is like this :
Component | AVG Duration (October) | AVG Duration (November) | AVG Duration (December) |
---|---|---|---|
Component one | 40 | ||
Component one | 15 | ||
Component one | 25 |
It's probably the group-by expression having the log_timestamp, but if I remove that one the concat function just writes the average duration (of all months) in the first available month. I don't have any experience with pivotting tables so I'm a bit out of my depth here. Any help would be appreciated.
CodePudding user response:
Do it in 2 steps:
- Write a query to compute the averages.
- Write a query to pivot, using the step-1 query in a 'derived table'.
CodePudding user response:
Perhaps a final query like this:
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;
And prepared statement syntax of the following:
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;