2011-07-21 44 views
14

我想要array_agg与Postgresql中的数组类型一起工作,我很难弄清楚这是否可能,如果有的话如何做到这一点。我查询的相关部分看起来是这样的:array_agg为阵列类型

array_agg(ARRAY[e.alert_type::text, e.id::text, cast(extract(epoch from e.date_happened) as text)] order by e.date_happened asc, e.id asc) 

,我在响应我得到是ERROR: could not find array type for data type text[]

这是可能的,或者我应该尝试寻找另一种方法错误?

谢谢!

回答

8

你可以编写自定义的聚集来处理你的阵列的特定阵列,例如:

DROP TABLE IF EXISTS e; 
CREATE TABLE e 
(
    id serial PRIMARY KEY, 
    alert_type text, 
    date_happened timestamp with time zone 
); 

INSERT INTO e(alert_type, date_happened) VALUES 
    ('red', '2011-05-10 10:15:06'), 
    ('yellow', '2011-06-22 20:01:19'); 

CREATE OR REPLACE FUNCTION array_agg_custom_cut(anyarray) 
RETURNS anyarray 
    AS 'SELECT $1[2:array_length($1, 1)]' 
LANGUAGE SQL IMMUTABLE; 

DROP AGGREGATE IF EXISTS array_agg_custom(anyarray); 
CREATE AGGREGATE array_agg_custom(anyarray) 
(
    SFUNC = array_cat, 
    STYPE = anyarray, 
    FINALFUNC = array_agg_custom_cut, 
    INITCOND = $${{'', '', ''}}$$ 
); 

查询:

SELECT 
    array_agg_custom(
     ARRAY[ 
      alert_type::text, 
      id::text, 
      CAST(extract(epoch FROM date_happened) AS text) 
     ]) 
FROM e; 

结果:

   array_agg_custom    
-------------------------------------------- 
{{red,1,1305036906},{yellow,2,1308787279}} 
(1 row) 

编辑:

这里是第二较短的方式(也就是,你不需要array_agg_custom_cut功能,但是当你看到其他ARRAY水平是必要的查询):

CREATE AGGREGATE array_agg_custom(anyarray) 
(
    SFUNC = array_cat, 
    STYPE = anyarray 
); 

SELECT 
    array_agg_custom(
     ARRAY[ 
      ARRAY[ 
       alert_type::text, 
       id::text, 
       CAST(extract(epoch FROM date_happened) AS text) 
      ] 
     ]) 
FROM e; 

结果:

   array_agg_custom    
-------------------------------------------- 
{{red,1,1305036906},{yellow,2,1308787279}} 
(1 row) 
+0

感谢您的提示。我使用了第二种方法,除了我创建了一个新的多态函数array_append(anyarray,anyarray) - 它只是'选择array_cat($ 1,ARRAY [$ 2])',然后使用array_append作为我的自定义聚合函数的SFUNC。这样,不需要外部的ARRAY []包装,这使得用户可见的SQL看起来更简单。 :) – dannysauer

3

或将数组转换为像array_agg(array [xxx,yyy] :: text)的文本

array_agg(ARRAY[e.alert_type::text, e.id::text, 
cast(extract(epoch from e.date_happened) as text)]::text 
order by e.date_happened asc, e.id asc) 
+1

只要你使用regexp_replace()来摆脱不需要的字符,就可以作为一种魅力。 – MarHoff