postgres - 通过不同的目标和平均数据获取数据 - 到目前为止没有运气

时间:2014-04-10 15:34:40

标签: python postgresql

主要问题:"目前我所有传感器的平均温度是多少?平均角度是多少?平均数据库级别?"

所以我有一个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)

1 个答案:

答案 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

由于加入,您可能希望对ddinstancenametime编制索引,以便从此查询中获得任何效果。