【问题标题】:How do I write this function in PL/pgSQL如何在 PL/pgSQL 中编写此函数
【发布时间】:2012-07-19 23:36:54
【问题描述】:

我有一个具有以下架构的表:

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()

【问题讨论】:

  • 定义顺序。什么是“以前的”?

标签: postgresql stored-procedures plpgsql window-functions


【解决方案1】:

假设“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');

【讨论】:

  • 谢谢欧文。除了冗长/简洁的 PostgreSQl 文档(其中大部分没有提供有用的示例)之外,是否有一个链接或一本书可以推荐我阅读,以便能够编写我自己的查询并增加我的SQL知识?例如WITHGREATEST 对我来说是新关键字,我仍然不完全了解如何使用窗口函数,这意味着我将简单地复制并粘贴您提供的代码,而没有真正了解它是如何工作的。
  • 我从优秀的手册和尝试中学到的最多。好吧,还有大学的基础知识。您可以浏览 SO - 尝试搜索。有很多有用的例子。或dba.SE。仅我一个人就使用窗口函数发布了数十个答案。我已经使用 PostgreSQL 将近 15 年了,不要指望一天就能学会。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
相关资源
最近更新 更多