有没有办法引用前一行的计算值并在下一行的计算中使用它?
Posted
技术标签:
【中文标题】有没有办法引用前一行的计算值并在下一行的计算中使用它?【英文标题】:Is there a way to reference a calculated value from the previous row and use that in the next row's calculation? 【发布时间】:2020-01-07 06:00:12 【问题描述】:例如,我有以下查询和表:
SELECT generate_series * 5 as num
FROM generate_series(1, 5)
+-----+
| val |
+-----+
| 5 |
| 10 |
| 15 |
| 20 |
| 25 |
+-----+
但是我想取上一行的 val 并不断地将它乘以 5,这样我就得到了表格:
+-----+
| val |
+-----+
| 5|
| 25|
| 125|
| 625|
| 3125|
+-----+
我知道我可以直接使用 5 ^ row_number
,但我需要解决的问题要求我设计查询以便能够引用上一行计算的 val
【问题讨论】:
源表为每日股价报价 使用5 ^ n
,然后将查询用作子查询,并在外部查询中使用lag
来访问上一行的计算值。
【参考方案1】:
我终于发现我需要一个自定义聚合函数来从这个线程调用:How to create a custom windowing function for PostgreSQL? (Running Average Example)
最终结果是这样的。它需要 2 个十进制值,第一个是要相乘的值,而第二个是默认值。
CREATE OR REPLACE FUNCTION prod(decimal, decimal, decimal) RETURNS decimal
LANGUAGE SQL AS $$
SELECT ROUND(COALESCE($1 * $2, $3), 2);
$$;
DO $$ BEGIN
CREATE AGGREGATE prods ( decimal, decimal ) (
SFUNC = prod,
STYPE = decimal
-- INITCOND = 1.0
);
EXCEPTION
WHEN duplicate_function THEN NULL;
END $$;
调用方式:
prods(val, 5) OVER (ORDER BY val)
【讨论】:
【参考方案2】:使用滞后窗口函数,假设滞后是您的排序列
select val, val*coalesce(Lag(val,1) OVER ( ORDER BY val),1) as product from tbl
【讨论】:
感谢@zip 的回答!但是我需要根据上一行的product
计算行的product
,而不参考上一行的val
嗨@Lorenzo,我很困惑,你说“我想取前一行的 val 但是并不断地将它乘以 5,这样我就得到了表格:”但是在评论中你是说你不想引用上一行的 val。
那是我的错,对不起!我用词错了。我认为解释我的问题的更好方法是使用前一行的产品来计算该行的产品。 SELECT COALESECE(LAG(product, 1) OVER (ORDER BY val) * 5, 1) as product
之类的问题是我无法在其内部引用产品【参考方案3】:
我有点不明白为什么需要自定义聚合函数。这是一个简单的算术级数。为什么不这样做呢?
SELECT gs.*,
power(5, gs.x)
FROM generate_series(1, 5) gs(x);
或者如果您真的想保留原始数据:
SELECT gs.x * 5,
power(5, ROW_NUMBER() OVER (ORDER BY ts.x))
FROM generate_series(1, 5) gs(x);
【讨论】:
为了简化问题,我使用了该表,但我可以看到我可以更好地“简化”它。我的真实数据的问题是我需要能够做到这一点,因为我会将前一行的值与当前行上的不同值相乘。 @LorenzoAng 。 . .我建议你问一个新的、更好的问题。我认为不需要客户聚合功能。 我很抱歉。我的问题措辞错误,但这并没有改变我需要自定义聚合函数的事实。我会记住的,下次会更清楚。以上是关于有没有办法引用前一行的计算值并在下一行的计算中使用它?的主要内容,如果未能解决你的问题,请参考以下文章