我有一个仪表读数表,其中包含一个米,没有读数值和读数。
我想显示每年每年读数的总和。
例如:
SELECT meterNo, SUM(readingValue) '2009' FROM readings
WHERE readingDate >= '2009-01-01' AND readingDate <= '2009-12-31'
GROUP BY meterNo;
将显示表格:
meterNo 2009
--------------
4 50
5 5
12 30
13 63
18 18
26 484
27 21
28 510
29 28
这就是我想要的,它显示了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
等等......
我可以重用查询的where部分:
WHERE readingDate >= '2009-01-01' AND readingDate <= '2009-12-31'
只需更改每年的日期,但如何在一个结果表中显示每个WHERE结果作为自己的列?
答案 0 :(得分:7)
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;
但是,如果要将未知数量的值或要作为新年度调整的查询添加到数据库中,那么可以使用预准备语句生成动态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;
见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 |
作为旁注,如果您希望null
在没有值而不是零的行中显示,则可以删除else 0
(请参阅Demo)
答案 1 :(得分:2)
您可以使用CASE WHEN执行此操作。它允许您根据多个条件对多个值求和。在你的例子中,你可以做这样的事情(我简化了我的例子,因为我无法访问你的实际数据):
SELECT meterNo,
sum(CASE WHEN readingDate = 2009 THEN readingValue END) as '2009',
sum(CASE WHEN readingDate = 2010 THEN readingValue END) as '2010',
sum(CASE WHEN readingDate = 2011 THEN readingValue END) as '2011',
sum(CASE WHEN readingDate = 2012 THEN readingValue END) as '2012'
FROM readings
GROUP BY meterNo
您需要使用自己的条件切换条件 - sum(CASE WHEN readingDate >= '2009-01-01' AND readingDate <= '2009-12-31' THEN readingValue END)
等 - 但它应该有效。这是我在sqlFiddle上做的一个工作示例:http://sqlfiddle.com/#!2/6990e/29。输出为五列,每个米的总和没有。
答案 2 :(得分:0)
你可以这样做:
SELECT
meterNo, SUM(readingValue) AS `total`, YEAR(readingDate)
FROM
readings
GROUP BY
meterNo, YEAR(readingDate);
结果:
METERNO TOTAL YEAR(READINGDATE)
1 90 2009
1 90 2010
2 50 2009
3 80 2009
3 40 2010
另请注意如何使用YEAR
函数而不是where子句。