我有以下问题...
Time | A | B | C -- Sum should be
1 a1 b1 c1 a1 + b1 + c1
2 a2 b2 x a2 + b1 + c1
3 a3 x x a3 + b2 + c1
4 x b3 c2 a3 + b3 + c2
基本上,总和需要跨越最近的值 及时为三行中的每一行。每个数据列都没有 必须具有当前时间的值。
我尝试了几种使用窗口函数的方法 没有成功。我写了一个存储过程 做我需要的,但它是缓慢的。
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);
答案 0 :(得分:1)
SELECT ts, a, b, c
, COALESCE(max(a) OVER (PARTITION BY grp_a), 0)
+ COALESCE(max(b) OVER (PARTITION BY grp_b), 0)
+ COALESCE(max(c) OVER (PARTITION BY grp_c), 0) AS special_sum
FROM (
SELECT *
,count(a) OVER w AS grp_a
,count(b) OVER w AS grp_b
,count(c) OVER w AS grp_c
FROM t
WINDOW w AS (ORDER BY ts)
) sub
ORDER BY ts;
首先,将实际值和NULL
值放在具有聚合窗口函数count()
的组中:它不会随NULL
值递增。
然后从每个小组中取出max()
,到达您要找的内容。此时,您也可以使用min()
或sum()
,因为每个组只有一个非空值。
COALESCE()
,则 NULL
会捕获NULL
个值。
请注意我选择ts
作为列名,因为我不使用time
等基本类型名称作为标识符。
这也是你们每个人应该首先提供样本数据的方式!
CREATE TEMP TABLE t (ts int, a int, b int, c int);
INSERT INTO t VALUES
(1, 11, 21, NULL)
,(2, 12, 22, NULL)
,(3, 13, NULL, NULL)
,(4, NULL, 23, 32);