我有一个设备可以读取电子设备的kw值,以测量它们(能量消耗的速率)在某个时间。然后将这些值发送到轮询器(定期向设备询问值),并插入到数据库中。
示例:
1st reading - 10 kw at 1.01pm 2nd reading - 15 kw at 1.23pm 3rd reading - 11 kw at 1.30pm
如您所见,轮询间隔不固定,因此可以在不同时间将值插入数据库。为简单起见,我们可以想象数据库只是一个包含2列的表,[时间]和[kw_value]。
这实际上是一个两部分问题:
如何从这些读数中获取每日kwh值(全天的能耗)?我在数学上非常糟糕,所以我不知道从这些值中获得每日kwh值的正确方法是什么。
我想把所有的值加起来并得到平均值,但我的妈妈说我应该绘制一整天所有读数的图表,然后得到绘制线下面的区域(有点像得到图表的积分,然后给出我当天消耗的总功率。然后我应该用这个值除以整天的持续时间,以小时为单位得到千瓦时,是吗?
如何使用数据库执行此操作?如果一天有数千个读数(来自多个电子设备,在这种情况下我们有3列 - [时间],[kw_value],[deviceid]),如果我加载所有值,我应该如何计算内存(我使用C#)并从那里计算或者我可以使用SQL来计算它吗?
编辑: 谢谢你们指出kw和kwh之间的区别。我的原始问题犯了大错,因此编辑。重申一下,设备在特定时间读取kw值(能量消耗率,以千焦耳/秒为单位),并在数据库中给出这些值的列表/图表,确定kwh的正确方法是什么(给定的一天消耗的总能量)。
答案 0 :(得分:0)
此查询查找每行的上一行。然后对于每个区间,它假设整个区间从一开始就具有kwh值。
; with numbered as
(
select *
, row_number() over (partition by deviceid order by time) rn
from YourTable
)
select deviceid
, sum(t0.kwh_value * datediff(s, t0.[time], t1.[time])/3600)
from numbered t1
join numbered t0
on t1.deviceid = t0.deviceid
and t1.rn = t0.rn + 1
group by
deviceid
您可以修改查询以计算使用间隔的平均千瓦时:
, sum((t1.kwh_value + t0.kwh_value)/2 * datediff(s, t0.[time], t1.[time])/3600)
答案 1 :(得分:0)
我的解决方案试图处理日间隔和测量间隔的重叠:
public class Measurement
{
public DateTime t;
public double kwh;
public Measurement(string t, double kwh)
{
this.t = DateTime.Parse(t);
this.kwh = kwh;
}
}
public static double getPowerConsumption(IEnumerable<Measurement> measurements, DateTime day)
{
DateTime never = DateTime.MinValue;
DateTime tomorrow = day.AddDays(1);
DateTime prev = never;
double kwh = 0;
foreach (Measurement m in measurements)
{
if (m.t >= day)
// measurement in our after or day
{
if (m.t >= tomorrow)
{
if ((prev != never) && (prev < m.t))
{
// add portion up to midnight
kwh += m.kwh * (tomorrow.Ticks - prev.Ticks) / (double)(m.t.Ticks - prev.Ticks);
}
break;
}
else if ((prev != never) && (prev < day) && (prev < m.t))
{
kwh += m.kwh * (m.t.Ticks - day.Ticks) / (double)(m.t.Ticks - prev.Ticks);
}
else
{
kwh += m.kwh;
}
}
prev = m.t;
}
return kwh;
}
static void Main(string[] args)
{
DateTime myDay = new DateTime(2012, 11, 2);
List<Measurement> measurements = new List<Measurement>() { new Measurement("01.11.2012 23:30", 10),
new Measurement("02.11.2012 10:00", 1),
new Measurement("02.11.2012 23:30", 5),
new Measurement("03.11.2012 10:00", 6) };
double kwh = getPowerConsumption(measurements, myDay);
Console.WriteLine("Powerconsumption for " + myDay.ToShortDateString() + " was " + kwh.ToString("#.##") + "kWh");
}
答案 2 :(得分:0)
你肯定不会得到精确的千瓦时价值。由于这种不常见的轮询频率,您最终可能会在估算和实际使用之间出现非常大的差异。你举了这个例子:
1st reading - 10 kW at 1.01pm
2nd reading - 15 kW at 1.23pm
3rd reading - 11 kW at 1.30pm
没有其他信息,关于唯一合理的做法是平均每对读数和多个读数。从1.01到1.23是22分钟,或.367小时。该期间的平均读数为(10 + 15)/ 2或12.5 kW,估计使用量为(12.5 * 0.367)或4.58 kWh。
但是,这种方法有一些明显的漏洞。如果实际消费是:,会发生什么10 kW at 1.01pm
0 kW at 1.02pm // machine turned off
15 kW at 1.23pm // machine turned back on
11 kW at 1.29pm
您在1.01和1.23之间的实际使用时间为10千瓦,一分钟或0.16千瓦时。
在另一个方向上,这些数字可能会有相似的数量。也就是说,你的计算结果可能非常低。
如果这是合理的,我的方法是创建一个SQL查询,返回按机器排序的数据,然后按时间返回。所以你得到:
machine1, 1.01 am, reading
machine1, 1.20 am, reading
... etc. ...
machine2, 1.03, reading
machine2, 2.15, reading
所以机器1的所有读数都按时间顺序呈现给你,然后是机器2等等。
您当然可以使用ORDER BY和GROUP BY编写查询,以正确的顺序返回所有读数。然后,您可以使用SqlDataReader
按顺序移动结果,计算每个时段的消耗(使用上面显示的平均值计算),并对每台机器的结果求和。我不太清楚SQL是否可以说是否可以编写一个查询来为您完成所有计算并返回一个结果集,例如:
machine1, start time, end time, total power consumed
machine2, start time, end time, total power consumed
etc