MySQL按年分组统计各季度太阳能发电量的SQL写法
问题场景
现有存储10年太阳能面板发电数据的MySQL表DTP,数据采集粒度为每10分钟1条,仅保存发电量大于0的记录,表结构如下:
#, Field, Type, Null, Key, Default, Extra 1, 'PWR', 'decimal(5,3)', 'NO', '', NULL, '' 2, 'idDTP', 'int(11)', 'NO', 'PRI', NULL, 'auto_increment' 3, 'DT', 'datetime', 'NO', '', NULL, ''
需求为构造SQL查询,实现结果按年份分行,每行返回4个统计值,分别对应该年度Q1-Q4四个季度的发电功率PWR总和。
此前尝试的问题
之前参考其他业务场景的SQL示例改造的代码无法正常运行,不确定实现思路是否正确,改造后的错误代码如下:
SELECT Year,SUM(Quarter1) AS Quarter1,SUM(Quarter2) AS Quarter2,SUM(Quarter3) AS Quarter3,SUM(Quarter4) AS Quarter4 FROM ( SELECT YEAR(DT) AS 'Year' , Quarter1 = CASE(DATEPART(q, DTP.DT)) WHEN 1 THEN SUM(DTP.DT) ELSE 0 END, Quarter2 = CASE(DATEPART(q, DTP.DT)) WHEN 2 THEN SUM(DTP.DT) ELSE 0 END, Quarter3 = CASE(DATEPART(q, DTP.DT)) WHEN 3 THEN SUM(DTP.DT) ELSE 0 END, Quarter4 = CASE(DATEPART(q, DTP.DT)) WHEN 4 THEN SUM(DTP.DT) ELSE 0 END FROM DTP LEFT JOIN PWR ON DTP.DT = Customers.CustomerID LEFT JOIN [Order Details] ON [Order Details].OrderID = Orders.OrderID GROUP BY CompanyName, YEAR(OrderDate), DATEPART(q, OrderDate) )C GROUP BY CompanyName,Year
以下为2012年2-3月的部分源数据样例,全量数据格式与样例一致:
'160851', '2012-02-29 08:00:00', '0.030' '160852', '2012-02-29 08:10:00', '0.066' '160853', '2012-02-29 08:20:00', '0.072' '160854', '2012-02-29 08:30:00', '0.060' '160855', '2012-02-29 08:40:00', '0.090' '160856', '2012-02-29 08:50:00', '0.102' '160857', '2012-02-29 09:00:00', '0.084' '160858', '2012-02-29 09:10:00', '0.132' '160859', '2012-02-29 09:20:00', '0.144' '160860', '2012-02-29 09:30:00', '0.138' '160861', '2012-02-29 09:40:00', '0.150' '160862', '2012-02-29 09:50:00', '0.174' '160863', '2012-02-29 10:00:00', '0.174' '160864', '2012-02-29 10:10:00', '0.162'
实现思路
- 采用条件聚合的方式完成行转列统计,不需要冗余的多表关联、嵌套子查询
- MySQL中使用内置
QUARTER(日期字段)函数获取日期所属季度,返回值为1-4,分别对应Q1到Q4 - 直接按年份分组,分组内通过
CASE WHEN判断每条记录所属季度,匹配对应季度时返回功率值PWR,否则返回0,再对返回值求和即可得到对应季度的功率总和
可直接运行的正确SQL
SELECT YEAR(DT) AS `Year`, SUM(CASE WHEN QUARTER(DT) = 1 THEN PWR ELSE 0 END) AS Quarter1, SUM(CASE WHEN QUARTER(DT) = 2 THEN PWR ELSE 0 END) AS Quarter2, SUM(CASE WHEN QUARTER(DT) = 3 THEN PWR ELSE 0 END) AS Quarter3, SUM(CASE WHEN QUARTER(DT) = 4 THEN PWR ELSE 0 END) AS Quarter4 FROM DTP GROUP BY YEAR(DT) ORDER BY `Year`;
原有代码错误点说明
- 残留参考示例的无关逻辑:关联了当前场景不存在的
PWR、Customers、Orders、Order Details业务表,关联条件也完全不匹配 - 数据库函数不兼容:
DATEPART是SQL Server的日期函数,MySQL无该语法 - 聚合逻辑错误:
CASE语句内错误嵌套聚合函数,且求和字段误写为时间字段DT,而非需要统计的功率字段PWR - 分组字段错误:分组用的
CompanyName、OrderDate等字段在DTP表中不存在,属于示例代码残留
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

