我正在使用Postgres 9.2。使用設備的最新數據求和一系列設備標記的數據
我有以下問題:
Time | Value | Device -- Sum should be
1 v1 1 v1
2 v2 2 v1 + v2
3 v3 3 v1 + v2 + v3
4 v4 2 v1 + v4 + v3
5 v5 2 v1 + v5 + v3
6 v6 1 v6 + v5 + v3
7 v7 3 v6 + v5 + v3
從本質上講,總和必須跨越的最新值 的時間爲每年的N個器件。在上面的例子中, 是3個設備。
我已經嘗試了幾種使用窗口函數的方法,並且 已經失敗。我寫了一個存儲過程,它可以滿足我需要,但速度很慢。 SLOWness可能是我的 缺乏plpgsql的經驗。
CREATE OR REPLACE FUNCTION timeseries.combine_series(id int[], startTime timestamp, endTime timestamp)
RETURNS setof RECORD AS $$
DECLARE
retval double precision = 0;
row_data timeseries.total_active_energy%ROWTYPE;
maxCount integer = 0;
sz integer = 0;
lastVal double precision[];
v_rec RECORD;
BEGIN
SELECT INTO sz array_length($1,1);
FOR row_data IN SELECT * FROM timeseries.total_active_energy WHERE time >= startTime AND time < endTime AND device_id = ANY($1) ORDER BY time
LOOP
retval = row_data.active_power;
for i IN 1..sz LOOP
IF $1[i]=row_data.device_id THEN
lastVal[i] = row_data.active_power;
ELSE
retval = retVal + COALESCE(lastVal[i],0);
END IF;
END LOOP;
SELECT row_data.time, retval into v_rec;
return next v_rec;
END LOOP;
return ;
END;
$$ LANGUAGE plpgsql;
電話:
select * from timeseries.combine_series('{552,553,554}'::int[], '2013-05-01'::timestamp, '2013-05-02'::timestamp)
AS (t timestamp with time zone, val double precision);
的樣本數據
CREATE OR REPLACE TEMP TABLE t (ts int, active_power real, device_id int, should_be int);
INSERT INTO t VALUES
(1,2,554,2)
,(2,3,553,5)
,(3,9,553,11)
,(4,7,553,9)
,(5,6,552,15)
,(6,8,554,21)
,(7,5,553,19)
,(8,7,553,21)
,(9,6,552,21)
,(10,7,552,22)
;
非常感謝。表現非常好。 – user2505340
我必須說,tablefunc功能是非常有用的。我希望我早些時候知道這件事。 – user2505340
@ user2505340:'crosstab()'處理複雜的邏輯,這對一些人來說是令人困惑的。但是一旦你可以圍繞它思考,你就可以獲得快速和緊湊的查詢。如果你有更多的用例 - 我在過去一年左右發佈了[相當多的綜合答案](http://stackoverflow.com/search?q=user%3A939860+ [crosstab])。 –