如何在带有 Postgres 的动态框架中使用窗口函数中的列值?

Posted

技术标签:

【中文标题】如何在带有 Postgres 的动态框架中使用窗口函数中的列值?【英文标题】:How Do I Use Column Value in Window Function for a Dynamic Frame with Postgres? 【发布时间】:2017-12-11 16:17:37 【问题描述】:

我不确定 Postgres 是否可以做到这一点,但我希望每一行都计算其窗口函数“框架”。

那么如何在 Postgres 的窗口函数中使用当前行中的列作为 ROWS 的参数?

例如..

create table items (
  id serial primary key, name varchar, price integer, precede_by integer
);

insert into items (name, price, precede_by) 
  values 
  ('A', 1, 2), ('A', 1, 3), 
  ('B', 1, 1),('B',1, 2), ('B', 1, 1), ('B', 2, 2), 
  ('C', 1, 2), ('C', 1,2), ('C', 1, 2), ('C', 1, 5);

我想使用在precede_by 列中设置的整数值。例如,像这样..

select name, sum(price) over 
  (partition by name rows between precede_by preceding and current row) 
from items;

但这不起作用。我收到ERROR: argument of ROWS must not contain variables

【问题讨论】:

你也错过了order byname 的顺序是什么? 我并不真正关心它们是如何排序的。在这个例子中,我只是好奇如何将行中的值用于动态窗口函数框架。 order by 能解决这个问题吗? @seanb123 这无助于解决这个问题,不。但是...如果没有它,您的结果将是无稽之谈(假设您在这里破解了变量坚果)。 另外,有一列表明您的当前记录与在当前记录之前排序的其他一些记录之间存在关系似乎不是那么好的设计。这表明表中的记录存在一些固有的顺序,而没有。似乎 category_id 或父/子关系在这里更适合对您的记录进行分组。所以你可以sum(price) .. group by category_id 或者在递归 CTE 中做一些数学运算(如果它本质上更分层的话)。也许您可以根据您的样本数据分享您想要的结果 请查看Bruce Momjian's presentation它对我有帮助,所以也许它也可以帮助你。 【参考方案1】:

不,不可能随心所欲地编写窗口函数。我相信CROSS JOIN LATERAL 可以解决问题

with oitems as
(
  select *, row_number() over (partition by name order by id) rn from items
)
select * 
from oitems i1
cross join lateral 
(
  select sum(price) 
  from  oitems i2
  where i1.name = i2.name and i2.rn >= i1.rn - i1.precede_by and i2.rn <= i1.rn
) t

另一个(可能更优雅)的解决方案是使用 GROUP BY 的自联接

with oitems as
(
  select *, row_number() over (partition by name order by id) rn from items
)
select i1.id, i1.name, i1.price, sum(i2.price) 
from oitems i1
join  oitems i2 on i1.name = i2.name and i2.rn >= i1.rn - i1.precede_by and i2.rn <= i1.rn
group by i1.id, i1.name, i1.price

dbfiddle demo

【讨论】:

是的,这可以完成我最终追求的目标。谢谢!但不能解决窗口函数中的动态框架。但我喜欢这个解决方案,因为我不知道我希望通过窗口功能实现的目标是否可行。谢谢。

以上是关于如何在带有 Postgres 的动态框架中使用窗口函数中的列值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用窗口函数仅在 POSTGRES 中选择不超过某个值的行

如何在 SQL Server 中使用带有框架的窗口函数执行 COUNT(DISTINCT)

如何在 Postgres 的窗口函数中获取 mode()?

如何在 Postgres 查询窗口中使用参数测试我的 ad-hoc SQL

如何在 JSONField 中使用 Postgres 在 Django 中搜索带有空格的键?

如何在 Postgres 中使用带有多个分位数的 percentile_conts