主要问题:"目前我所有传感器的平均温度是多少?平均角度是多少?平均数据库级别?"
所以我有一个python脚本,每15分钟循环一次,用来自http get操作的数据填充postgres表(xmldata)。该表很可能有1,000,000多条记录。此表和数据如下所示:
fieldtest2=> select * from xmldata limit 7;
id | time | ddinstancename | dcchannelname | dcdintegervalue
----+----------------------------+----------------+---------------+-----------------
1 | 2014-02-18 12:51:00.561153 | targ_4079E741 | AD1 | 641
2 | 2014-02-18 12:51:04.568751 | targ_40971E83 | AD1 | 641
3 | 2014-02-18 12:51:08.535351 | targ_4079E741 | AD0 | 641
4 | 2014-02-18 12:51:12.90712 | targ_4079E741 | AD1 | 641
5 | 2014-02-18 12:51:16.863364 | targ_40971E83 | AD1 | 641
6 | 2014-02-18 13:15:48.109646 | targ_40971E83 | AD0 | 589
7 | 2014-02-18 13:15:48.463776 | targ_4079E741 | AD1 | 653
现在,我坚持的部分。我想从每个唯一 ddinstancename获取最新的dcdinteger值(由于表的大小,只返回一两个小时),按dcchannelname对它们进行分组,并平均每个组的dcdinteger值。所以基本上例如,每个" AD1"是温度读数。我希望从每个唯一的ddinstancename获取最新的AD1数据捕获。在上面的例子中,那将是记录id 5和7.然后我想平均他们的dcdinteger值,所以641 + 653/2 = 647并将该平均值保存到另一个表,sensoraverage:
fieldtest2=> select * from sensoraverage;
id | time | dcchannelname | channelaverage
----+------+---------------+----------------
(0 rows)
所以基本上你得到的快照是,目前所有目标的平均温度为647,平均x角为111,平均db水平为234 ......等。
我一直在尝试多种变化,然后将其缩小。正如我所说,但以下的硬代码'目前有问题的频道,没有订购或限制,只是为了尝试让事情变得有效。我的想法是我只为每个dcchannelname做一个单独的查询。但可能有更好的方法。我应该把它分成几个单独的查询吗?
只有4个不同的dcchannelname&#39。可能有数百个不同的ddinstancename。
avgTemp_query = "INSERT into sensoraverage (dcChannelName, channelaverage) VALUES (('AD0'), (SELECT DISTINCT ddInstanceName, AVG(dcdIntegerValue) FROM xmldata WHERE dcChannelName='AD0'));"
我想从我所读到的内容来看,明显不会像我认为的那样运作。 任何指导将不胜感激。 谢谢 麦克
更新:基于Lucas'答案似乎很接近。我认为我遇到的问题是时间戳。我将此作为评论添加到Lucas'发布但是太长了......
我想知道是否需要重新执行如何将这些记录条目时间戳到xmldata中,如果这可能是问题。这是我最近的尝试(我也试过now():: date - 100尝试以任何方式捕获任何东西而没有运气):
尝试直接匹配实际上只会产生一个结果(参见下表),但会产生一整套平均值。我还没有能够根据匹配确定使用的值,以弥补平均值。但我觉得它很接近。我很抱歉格式化,但我把这一切都放在一行中,通过我的终端运行...
fieldtest2=> WITH distinct_instances AS(
SELECT ddInstanceName
FROM xmldata
WHERE time = '2014-02-18 12:51:00.561153'
GROUP BY ddInstanceName HAVING count(*) = 1)
SELECT dcChannelName, avg(dcdintegervalue)
FROM distinct_instances
JOIN xmldata ON xmldata.ddInstanceName = distinct_instances.ddInstanceName
GROUP BY dcChannelName
ORDER BY dcChannelName;
dcchannelname | avg
---------------+----------------------
AD0 | 621.5416666666666667
AD1 | 648.6153133797599644
AD2 | 258.8515185601799775
AD3 | 324.5770528683914511
(4 rows)
fieldtest2=> select * from xmldata WHERE time = '2014-02-18 12:51:00.561153';
id | time | ddinstancename | dcchannelname | dcdintegervalue
----+----------------------------+----------------+---------------+-----------------
1 | 2014-02-18 12:51:00.561153 | targ_4079E741 | AD1 | 641
(1 row)
答案 0 :(得分:1)
我认为这就是你要找的东西
-- first get a set of the distinct instances within the last time period (here it is 1 hour)
-- then join that result set back to the table and group it by the channel name
WITH distinct_instances AS(
SELECT
ddinstancename,
FROM xmldata
WHERE time > now() - '1 hour'::interval
GROUP BY ddinstancename
HAVING count(*) = 1
)
SELECT
dcchannelname,
avg(dcdintegervalue)
FROM distinct_instances
JOIN xmldata ON xmldata.ddinstancename = distinct_instances.ddinstancename
GROUP BY dcchannelname
ORDER BY dcchannelname
由于加入,您可能希望对ddinstancename
和time
编制索引,以便从此查询中获得任何效果。