Dav*_*veM 1 mysql sql database pivot
我有一个仪表读数表,其中包含一个米,没有读数值和读数日期.
我想显示每年每年读数的总和.
例如:
SELECT meterNo, SUM(readingValue) '2009' FROM readings
WHERE readingDate >= '2009-01-01' AND readingDate <= '2009-12-31'
GROUP BY meterNo;
Run Code Online (Sandbox Code Playgroud)
将显示表格:
meterNo 2009
--------------
4 50
5 5
12 30
13 63
18 18
26 484
27 21
28 510
29 28
Run Code Online (Sandbox Code Playgroud)
这就是我想要的,它显示了2009年每个仪表的总读数值.但是,我需要结果表来显示每年的一列.所以它会是这样的:
meterNo 2009 2010 2011 2012
--------------------------------
1 20 35 50
2 45 35
3 50 60
4 50 35 20 30
5 5 10 10 15
6 30
Run Code Online (Sandbox Code Playgroud)
等等...
我可以重用查询的where部分:
WHERE readingDate >= '2009-01-01' AND readingDate <= '2009-12-31'
Run Code Online (Sandbox Code Playgroud)
只需更改每年的日期,但如何在一个结果表中将每个WHERE结果显示为自己的列?
MySQL没有PIVOT函数,但您可以使用带CASE表达式的聚合函数将数据行转换为列.
如果您的数量有限years,那么您可以对查询进行硬编码:
select meterNo,
sum(case when year(readingDate) = 2009 then readingValue else 0 end) `2009`,
sum(case when year(readingDate) = 2010 then readingValue else 0 end) `2010`,
sum(case when year(readingDate) = 2011 then readingValue else 0 end) `2011`,
sum(case when year(readingDate) = 2012 then readingValue else 0 end) `2012`,
sum(case when year(readingDate) = 2013 then readingValue else 0 end) `2013`
from readings
group by meterno;
Run Code Online (Sandbox Code Playgroud)
但是,如果要将未知数量的值或要作为新年度调整的查询添加到数据库中,那么可以使用预准备语句生成动态SQL:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(CASE WHEN year(readingDate) = ',
year(readingDate),
' THEN readingValue else 0 END) AS `',
year(readingDate), '`'
)
) INTO @sql
FROM readings;
SET @sql
= CONCAT('SELECT meterno, ', @sql, '
from readings
group by meterno');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.两者都给出了结果:
| METERNO | 2009 | 2010 | 2012 | 2013 | 2011 |
----------------------------------------------
| 1 | 90 | 180 | 0 | 90 | 90 |
| 2 | 50 | 0 | 90 | 0 | 0 |
| 3 | 80 | 40 | 90 | 90 | 0 |
Run Code Online (Sandbox Code Playgroud)
作为旁注,如果要null在没有值而不是零的行中显示,则可以删除else 0(参见演示)