先前行数组的累积数组?
Posted
技术标签:
【中文标题】先前行数组的累积数组?【英文标题】:Cumulative array from previous rows array? 【发布时间】:2014-03-19 05:35:51 【问题描述】:是否存在将以前的数组合并为累积数组的查询,这将导致:
id array_field c_array
---------------------------------------------
1 one,two one,two
2 three one,two,three
3 four,five one,two,three,four,five
4 six one,two,three,four,five,six
【问题讨论】:
我很高兴您接受了我的回答,但在这种情况下,Erwin 提供的答案在我看来要好得多。你有什么理由接受我的吗? 【参考方案1】:这取决于您使用什么。似乎您的基表包含文本数组text[]
。
有除了这些函数之外,任何内置或用户定义的聚合 函数可以作为窗口函数使用
array_agg()
,但它作用于标量类型,不作用于数组类型。
但您可以轻松create your own aggregate function。
要聚合数组类型,请创建此聚合函数:
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
,STYPE = anyarray
,INITCOND = ''
);
此相关答案中的详细信息:Selecting data into a Postgres array
现在,这项工作非常简单:
SELECT array_agg_mult(array_field) OVER (ORDER BY id) AS result_array
FROM tbl
由于聚合是为polymorphic types 定义的,这适用于任何数组类型,而不仅仅是text[]
。
SQL Fiddle 包括列表中文本表示的替代解决方案。
【讨论】:
【参考方案2】:您可以使用recursive CTE。
SQLFiddle
数据:
-- drop table if exists sample_data;
create table sample_data (id int, arr varchar[]);
insert into sample_data
values
(1,ARRAY['One','Two','Three']),
(2,ARRAY['Four','Six']),
(3,ARRAY['Seven']);
查询:
with recursive cte as (
select
id, arr, arr as merged_arr
from
sample_data
where
id = 1
union all
select
sd.id, sd.arr, cte.merged_arr || sd.arr
from
cte
join sample_data sd on (cte.id + 1 = sd.id)
)
select * from cte
结果:
1;One,Two,Three;One,Two,Three
2;Four,Six; One,Two,Three,Four,Six
3;Seven; One,Two,Three,Four,Six,Seven
【讨论】:
【参考方案3】:你需要一个 UPDATE
,其 CTE 指向前一个 id:
WITH prev AS (SELECT id, c_array AS prev_array FROM your_table)
UPDATE your_table
SET c_array = prev_array || array_field
FROM prev
WHERE id = prev.id + 1;
如果您想自动执行此操作,那么您需要一个 BEFORE INSERT
触发器,并且在触发器函数中您只需执行 SELECT c_array || NEW.array_field INTO NEW.c_array FROM your_table WHERE id = NEW.id - 1
如果 - 且仅当 - 您自己设置了 id。如果 id 来自一个序列,那么您需要一个带有上述更新的 AFTER INSERT
触发器。
【讨论】:
以上是关于先前行数组的累积数组?的主要内容,如果未能解决你的问题,请参考以下文章
Google Sheets ArrayFormula - 前行的平均值
对每一行应用一个函数,其中函数使用 DataFrame 的所有先前行