合并hstore多行数据

Chr*_* P. 0 postgresql aggregate hstore

假设我有一个具有此定义的表:

CREATE TABLE test (
  values HSTORE NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

想象一下,我插入一些记录并得到以下结果:

values
-----------------------------
"a"=>"string1","b"=>"string2"
"b"=>"string2","c"=>"string3"
Run Code Online (Sandbox Code Playgroud)

有什么办法可以使聚合查询为我提供一个新的hstore,其中包含所有行的合并键(和值)。

伪查询:

SELECT hstore_sum(values) AS value_sum FROM test;
Run Code Online (Sandbox Code Playgroud)

所需结果:

value_sum
--------------------------------------------
"a"=>"string1","b"=>"string2","c"=>"string3"
Run Code Online (Sandbox Code Playgroud)

我知道每个键具有不同值的潜在冲突,但是在我的情况下,选择值的顺序/优先级并不重要(它甚至不必是确定性的,因为对于同一键,它们将是相同的) 。

这可能是开箱即用的,还是您必须使用某些特定的自制SQL函数或其他函数来完成?

poz*_*ozs 5

您可以做很多事情,例如:

我的第一个想法是使用each()函数,并分别聚合键和值,例如:

SELECT  hstore(array_agg(key), array_agg(value))
FROM    test,
LATERAL each(hs);
Run Code Online (Sandbox Code Playgroud)

但这表现最糟。

您也可以使用该hstore_to_array()函数来构建键值更改数组,例如(@JakubKania):

SELECT  hstore(array_agg(altering_pairs))
FROM    test,
LATERAL unnest(hstore_to_array(hs)) altering_pairs;
Run Code Online (Sandbox Code Playgroud)

但这还不是完美的。

您可以依赖hstore值的表示形式,并构建一个字符串,其中将包含所有对:

SELECT  hstore(string_agg(nullif(hs::text, ''), ','))
FROM    test;
Run Code Online (Sandbox Code Playgroud)

这是相当快的。但是,如果需要,可以使用自定义聚合函数(可以使用内置hstore串联):

CREATE AGGREGATE hstore_sum (hstore) (
    SFUNC = hs_concat(hstore, hstore),
    STYPE = hstore
);

-- i used the internal function (hs_concat) for the concat (||) operator,
-- if you do not want to rely on this function,
-- you could easily write an equivalent in a custom SQL function

SELECT hstore_sum(hs)
FROM   test;
Run Code Online (Sandbox Code Playgroud)

SQLFiddle