MySQL SUM对具有多个值的查询

时间:2012-01-10 09:55:12

标签: php mysql sql sum fusioncharts

我有以下查询:

$strQuery = "SELECT siteid, SUM(watts) AS wattage, unit, device, time FROM inverter WHERE siteid = '528' AND time Between '$time1' AND '$time2' Order By device Asc";

我在融合图表中制作图表并且需要每个设备的总瓦数但是当我执行上面的查询时它会获取所有值并将它们放置在第一个设备上。我有40个设备,需要每个设备产生总瓦数。

在图表上,我将设备显示为x轴名称标签,将瓦数显示为值。

由于

3 个答案:

答案 0 :(得分:5)

SUM()是一个聚合函数,应与GROUP语句一起使用。如果省略GROUP语句,则将所有选定的行聚合为一个组。

请参阅文档:http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

查看GROUP BY声明:

SELECT siteid, device, 
  SUM(watts) AS wattage, 
  MIN(time) as start_time, 
  MAX(time) as end_time 
  unit
FROM inverter
WHERE siteid = '528' 
  AND time BETWEEN '$time1' AND '$time2'
GROUP BY device, unit
ORDER BY device ASC

此外,当您使用聚合并选择GROUP语句中未包含的字段(此处为:时间)时,您必须确保获得所需的值。

您为每个设备获得的聚合行的值是使用许多行计算的,这些行在这些字段中可能包含单个值。如果您不使用聚合函数(MINMAXAVG,..)来确定聚合行应包含多个值中的哪一个,您将收到一个选定的值或多或少由MySQL随机选择。

你应该

  • 如果没有必要,请不要选择此类字段。 (例如时间)
  • 对GROUP BY子句中未包含的每个字段使用适当的聚合函数(MINMAXAVG,..),以确保获得正确的值。 (这里我使用MINMAX插入了测量时间跨度的开始和结束时间)
  • 或将其包含在GROUP BY子句中 (我在示例中为“单位”做了这个,因为在兆瓦和千瓦上使用SUM时得到了错误的结果..我假设你使用的是“单位”?)

再次:否则此类字段中的结果值是随机的,而不是确定性的。

答案 1 :(得分:4)

您可以使用@Kaii和@cairnz提出的天真查询。

但是,如果所选设备有多个时间和单位,MySQL只会随机或多或少地选择一个设备的单位和时间。

为什么查询失败
使用正在使用聚合函数 除非您指定group by子句,否则聚合函数将简单地将所有行添加到1个聚合中 聚合函数中未涵盖的所有行将被压缩为一个项目(一个将简单地选择在leasure中)。

为了查看哪些数据不足,我建议:

SELECT 
  siteid
  , SUM(watts) AS wattage
  , GROUP_CONCAT(DISTINCT unit) as units
  , device
  , GROUP_CONCAT(time) as times 
FROM inverter 
WHERE siteid = '528' 
  AND time BETWEEN '$time1' AND '$time2' 
GROUP BY device
ORDER BY device ASC  

聚合函数GROUP_CONCAT将显示由聚合汇总在一起的所有(DISTINCT)值的逗号分隔列表。
由于您只按device进行分组,因此您将会将不同类型的unittime混为一谈。
添加到group by子句的列越多,您将“放大”数据的次数越多,显示的行数就越多。

为什么在列出group by 中不在的选项中的“裸”列时应小心谨慎 如果列出未在group by子句中列出的“裸”列(即不是聚合表达式的一部分),则这些列在功能上不依赖于group by子句。登记/> 将有多个不同的值,其中只显示一个值 这种行为是MySQL独有的,大多数其他SQL风格都会发出错误并拒绝。

MySQL允许这种危险行为的原因是 答:它允许更快的查询,
B:如果在group by子句中指定唯一键,则其他字段将在功能上依赖于该键(参见ANSI SQL 2003)并指定更多字段没有意义,
C:有时你不关心其他字段的值,显示随机代表就是你想要的。

为什么我不能只按列出组中的所有非聚合列 如果您更改group by语句,则会对输出产生深远影响 列数越多(直到您点击所选列的唯一键的位置)group by,您获得的详细信息就越多,这就取消了使用聚合函数的全部要点。

解决方案
如果你只想显示随机单位和时间,那当然很酷,但使用以下查询可能更有意义:

SELECT 
  siteid
  , SUM(watts) AS wattage
  , COUNT(*) as NumberOfUnits
  , device
  , MIN(time) as Mintime
  , MAX(time) as Maxtime
FROM inverter 
WHERE siteid = '528' 
  AND time BETWEEN '$time1' AND '$time2' 
GROUP BY device
ORDER BY device ASC  

您可以随意使用汇总功能,但请参阅: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

因为你正在使用MySQL,所以我认为。建议学习GROUP_CONCAT一个非常通用和有用的功能。

答案 2 :(得分:1)

您需要告诉分组的内容:

SELECT 
 siteid, 
 SUM(watts) AS wattage, 
 unit, 
 device, 
 MIN(time) AS StartTime,
 MAX(time) AS EndTime

FROM inverter 

WHERE siteid = '528' AND time Between '$time1' AND '$time2' 
GROUP BY siteid, unit, device
Order By device Asc

编辑:使用MIN()MAX()时间可以查看SUM()涵盖的时间段。您不应在查询中单独使用时间,而不指定单位/设备组合的瓦数总和的显示时间。