2017-09-16 2 views
1

Dans Postgres 9.x je peux faire comme çapostgresql créer ensemble avec commande par défaut et le paramètre

select dept_id, string_agg(user_id, ':' order by user_id) 
from dept_user 
group by dept_id; 
+---------+------------+ 
| dept_id | string_agg | 
+---------+------------+ 
| d1  | u1:u2:u3 | 
| d2  | u3:u4  | 
+---------+------------+ 

Mais ma compagnie utilise Postgres 8.3, donc je trouve une fonction d'agrégation peut faire comme string_agg

create schema WMSYS; 
create or replace function WMSYS.sf_concat(text,text) returns text as $$ 
    select case when coalesce($1, '') <> '' then $1||','||$2 else $2 end; 
$$ language sql called on null input; 
create aggregate WMSYS.wm_concat (text) (sfunc=WMSYS.sf_concat,stype=text); 

le résultat est:

select dept_id, WMSYS.wm_concat(user_id) 
from dept_user 
group by dept_id; 
+---------+-----------+ 
| dept_id | wm_concat | 
+---------+-----------+ 
| d1  | u3,u1,u2 | 
| d2  | u3,u4  | 
+---------+-----------+ 

Mais le résultat n'est pas trié (u3,u1,u2 doit être u1,u2,u3) et la chaîne de jointure (,) n'est pas un paramètre. Je veux utilisation comme ceci:

WMSYS.wm_concat(user_id)   ## join by ',' and don't sort 
WMSYS.wm_concat(user_id, ':')  ## join by ':' and don't sort 
WMSYS.wm_concat(user_id, ':', true) ## join by ':' and order by user_id 

comment faire?

+0

https://stackoverflow.com/a/2561297/330315 et https://stackoverflow.com/q/16455483/330315 –

Répondre

1

essayez ceci:

préparation échantillon de données:

t=# create table a1 (i int, t text); 
CREATE TABLE 
t=# insert into a1 select 1,'u'||g from generate_series(1,9,1) g; 
INSERT 0 9 
t=# update a1 set i =2 where ctid > '(0,4)'; 
UPDATE 5 
t=# select i,WMSYS.wm_concat(t) from a1 group by i; 
i | wm_concat 
---+---------------- 
1 | u1,u2,u3,u4 
2 | u5,u6,u7,u8,u9 
(2 rows) 

vient d'ajouter un autre argument:

create or replace function WMSYS.sf_concat(text,text,text) returns text as $$ 
    select case when coalesce($1, '') <> '' then $1||$3||$2 else $2 end; 
$$ language sql called on null input; 

create aggregate WMSYS.wm_concat (text,text) (sfunc=WMSYS.sf_concat,stype=text); 

t=# select i,WMSYS.wm_concat(t,':') from a1 group by i; 
i | wm_concat 
---+---------------- 
1 | u1:u2:u3:u4 
2 | u5:u6:u7:u8:u9 
(2 rows) 

maintenant, je ne savoir comment bien les fonctions de la fenêtre w ork en 8.3 et je ne env essayer si ce travaillerait:

t=# select i, max(t) from (select i,WMSYS.wm_concat(t,':') over (partition by i order by t desc) t from a1) a group by i; 
i |  max 
---+---------------- 
1 | u4:u3:u2:u1 
2 | u9:u8:u7:u6:u5 
(2 rows) 

mais comme Roman a suggéré, ce qui devrait:

t=# select i,WMSYS.wm_concat(t,':') from (select * from a1 order by i asc,t desc) a group by i; 
i | wm_concat 
---+---------------- 
1 | u4:u3:u2:u1 
2 | u9:u8:u7:u6:u5 
(2 rows) 

si vous contrôlez la commande pas comme argument pour agréger la fonction, mais avec la façon dont vous présentez les données

0

S'il vous plaît essayer:

SELECT dept_id, replace(WMSYS.wm_concat(user_id, ',', ':') 
    FROM (
     SELECT dept_id, user_id 
      FROM dept_user 
     ORDER BY 1, 2 
     ) AS A 
GROUP BY dept_id; 
+0

Cela peut faire ce que je veux, mais j'espère WMSYS.wm_concat' possède un paramètre pour contrôler la chaîne de jointure et le tri, alors la fonction sera facile à réutiliser. – lionyu

+0

Avertissement. Avec cette réduction, 'a, 1' rejoint' b, 2' était 'a: 1: b: 2' au lieu de' a, 1: b, 2'. –