【发布时间】:2020-03-01 04:03:52
【问题描述】:
假设给定一个表observations_tbl 具有属性date(天)和value,我想生成新属性prev_day_value 以获取下表:
|---------------------|-------|----------------|
| date | value | prev_day_value |
|---------------------|-------|----------------|
| 01.01.2015 00:00:00 | 5 | 0 |
| 02.01.2015 00:00:00 | 4 | 5 |
| 03.01.2015 00:00:00 | 3 | 4 |
| 04.01.2015 00:00:00 | 2 | 3 |
|---------------------|-------|----------------|
我很清楚这样的输出通常可以使用WINDOW 函数获得。但是我如何通过 PostgreSQL 用户定义的函数来实现这一点?我想表明我处于必须使用函数的情况,如果不详细说明,很难解释为什么 - 这些是我的限制,如果有的话,这是一个技术挑战。
考虑这个模板查询:
SELECT *, lag(value,1) AS prev_day_value -- or lag(record,1) or lag(date,value,1) or lag(date,1) or lag(observations_tbl,1), etc.
FROM observations_tbl
我正在使用带有参数1 的函数lag 来查找在当前行之前1 的值 - 1 行的距离。我不在乎函数lag 可以有哪些其他参数(表名、其他属性)- 函数lag 看起来像什么来实现这样的功能?该函数可以是任何语言,SQL、PL/pgSQL 甚至使用 PostgreSQL API/后端的C。
我知道一个答案可以是在 lag 用户定义的函数中包装 WINDOW 查询。但我认为,如果我必须扫描整个表两次(一次在 lag 函数内,一次在函数外),那将是一项相当昂贵的操作。我在想,也许每条 PostgreSQL 记录都会有一个指向它以前可以直接访问的记录的指针?或者我可以以某种方式在这个特定的行/行号处打开一个游标,而不必扫描整个表?或者我的要求是不可能的?
【问题讨论】:
-
尝试使用用户定义的函数来复制内置函数的效率似乎——我应该说——具有挑战性。
-
你确定PostgreSQL没有办法解决这个要求吗?
-
。 .不,我不知道。您可以围绕内部定义编写一个包装器。但是这样做的需要有些不对劲。这似乎是一个 X-Y 问题,您关注的是错误的细节。
-
您可以将功能内联到您的存储过程中,直到找到更好的方法来定位您的数据:/
-
如果您出于某些奇怪的原因“必须”使用函数,那么为什么不简单地将使用窗口函数的查询封装到 SQL 函数中呢?
标签: sql postgresql user-defined-functions plpgsql window-functions