我有一个包含以下架构的表:
CREATE TABLE foo (
the_date date,
user_id int,
pop REAL,
hip REAL,
lop REAL,
cop REAL
);
我想编写一个引用前一行的函数foofunc()
,并根据以下逻辑返回一个值:
function foofunc() returns numeric as $body$
begin
-- # calculate (current_row.hip - current_row.lop) as val1 for current row
-- # calculate abs(current_row.hip - previous_row.cop) as val2
-- # calculate abs(current_row.lop - previous_row.cop) as val3
-- RETURN max(val1, val2, val3)
end;
$body$ language plpgsql
我希望能够像这样调用函数foofunc()
:
SELECT foofunc()
from foo
where the_date between date1 and date2
and user_id=some_id;
如何实施foofunc()
?
答案 0 :(得分:2)
假设“previous”由the_date
..
实际上你并不需要一个plpgsql函数。带窗口函数的普通查询可以完成工作,而且速度也快得多:
WITH x AS (
SELECT *
,lag(cop,1,0::real) OVER (ORDER BY the_date) AS p_cop
FROM foo
WHERE the_date <= <date2> -- don't exclude earlier rows yet
AND user_id = <some_id>
)
SELECT GREATEST (
hip - lop
,@(hip - p_cop)
,@(lop - p_cop)
)
FROM x
WHERE the_date >= <date1>
ORDER BY the_date;
如果您确实需要一个功能:
CREATE OR REPLACE FUNCTION foofunc(_user_id int, _date date)
RETURNS real AS
$BODY$
BEGIN
RETURN (
WITH x AS (
SELECT *
,lag(cop,1,0::real) OVER (ORDER BY the_date) AS p_cop
FROM foo
)
SELECT GREATEST(
hip - lop
,@(hip - p_cop)
,@(lop - p_cop)
)
FROM x
WHERE the_date = _date
AND user_id = _user_id
);
END;
$BODY$ language plpgsql;
呼叫:
SELECT foofunc(1, '2012-07-21');