Project: YugabyteDB (App Definition and Development / Database)
File: array-string-jsonb-jsonb-object-agg.md

title: arrayagg(), stringagg(), jsonbagg(), jsonbobject_agg() linkTitle: arrayagg(), stringagg(), jsonbagg(), jsonbobject_agg() headerTitle: arrayagg(), stringagg(), jsonbagg(), jsonbobject_agg() description: Describes the functionality of the arrayagg(), stringagg(), jsonbagg(), jsonbobject_agg() YSQL aggregate functions menu: v2.18: identifier: array-string-jsonb-jsonb-object-agg parent: aggregate-function-syntax-semantics weight: 20 type: docs The aggregate functions `arrayagg()`, `stringagg()`, `jsonbagg()`, and `jsonbobjectagg()` are described in this same section because each produces, as a single value, a list_ of the values that are aggregated. (The term "list" is used informally and somewhat loosely here. The examples make the sense in which the word is used clear.) The notion "list" implies that the list members are ordered. (In contrast, "set" brings no such ordering notion.) For `arrayagg()`, `stringagg()`, `jsonbagg()`, and `jsonagg()`, the list order is determined by the `ORDER BY` clause in the `SELECT` list expression that invokes the aggregate function. Because the single value produced by `jsonbobjectagg()` (and `jsonobjectagg()`) is a JSON object, and because the elements of such a value have no order, the `ORDER BY` clause in the `SELECT` list expression has no effect. (The elements are accessed by field name.) This makes `arrayagg()`, `stringagg()`, and `jsonbagg()` unique among ordinary aggregate functions. Usually, as the example of `sum()` demonstrates, the order of the aggregated values is of no consequence. (The term "ordinary" aggregate function is used for the ones that are invoked with the `GROUP BY` syntax or the `OVER` syntax. The formal terms "within-group ordered-set" aggregate function and "within-group hypothetical-set" aggregate function_ are used for the "extraordinary" kinds.) Signature: ``` input value: anynonarray anyarray return value: anyarray ``` Purpose: Returns an array whose elements are the individual values that are aggregated. The to-be-aggregated values must be homogeneous: either all nonarray values; or all array values with the same dimensionality, as returned by , as each other. See also the account of in the dedicated section. The order of the resulting array elements (i.e. the mapping of element value to index value) is determined by the order defined by the `GROUP BY` or the `OVER` invocation syntax. When nonarray (i.e. scalar) values are aggregated, the result is a 1-dimensional array. When anyarray values with dimensionality N are aggregated, the result is an array with dimensionality (N + 1). Signature: ``` input value: text, text bytea, bytea return value: text bytea ``` Purpose: Returns a single value produced by concatenating the aggregated values (first argument) separated by a mandatory separator (second argument). The first overload has `text` inputs and returns `text`. The second overload has `bytea` inputs and returns `bytea`. (The PostgreSQL documentation describes the `bytea` data type in section . Here's a basic example: ```plpgsql drop table if exists t cascade; create table t(k int primary key, vt text not null, vb bytea not null); insert into t(k, vt, vb) values (1, 'm', 'm'::bytea), (2, 'o', 'o'::bytea), (3, 'u', 'u'::bytea), (4, 's', 's'::bytea), (5, 'e', 'e'::bytea); select vt, vb from t order by k; ``` This is the result: ``` vt | vb -+ m | \x6d o | \x6f u | \x75 s | \x73 e | \x65 ``` Now try this: ```plpgsql with a as ( select stringagg(vt, null order by k) as textagg, stringagg(vb, '.'::bytea order by k) as byteaagg from t) select text_agg, bytea_agg, convertfrom(byteaagg, 'utf-8') as byteaaggtext from a; ``` This is the result: ``` textagg | byteaagg | byteaaggtext -+-+- mouse | \x6d2e6f2e752e732e65 |

``` This aggregate function, together with `json_agg()`, are described fully in the section within the overall section. Signature: ``` input value: anyelement return value: jsonb ``` Purpose: Returns a JSON array whose elements are the JSON values formed from each of the to-be-aggregated values. This aggregate function, together with `jsonobjectagg()`, are described fully in the section within the overall section. Signature: ``` input value: "any", "any" return value: jsonb ``` Purpose: Returns a JSON object whose fields are the JSON elements formed by each of the to-be-aggregated value pairs. The first value in the pair provides the name (key) of the field and the second value in the pair provides its value. Because the order of key-value pairs in a JSON object is undefined (values are addressed by their key), the aggregation order has no effect on the result. Each of these aggregate functions is invoked by using the same syntaxeither the or the . First create and populate the test table: ```plpgsql drop table if exists t cascade; create table t( k int primary key, class int not null, v text not null); insert into t(k, class, v) select (1 + s.v), case (s.v) < 3 when true then 1 else 2 end, chr(97 + s.v) from generate_series(0, 5) as s(v); select k, class, v from t order by k; ``` This is the result: ``` k | class | v +-+ 1 | 1 | a 2 | 1 | b 3 | 1 | c 4 | 2 | d 5 | 2 | e 6 | 2 | f ``` Try this: ```plpgsql select class, arrayagg(v order by k desc) filter (where v <> 'b') as "arrayagg(v)", stringagg(v, ' ~ ' order by k desc) filter (where v <> 'e') as "stringagg(v)", jsonbagg(v order by v desc) filter (where v <> 'b') as "jsonbagg", jsonbobjectagg(v, k order by v desc) filter (where v <> 'e') as "jsonbobjectagg(v, k)" from t group by class order by class; ``` This is the result: ``` class | arrayagg(v) | stringagg(v) | jsonbagg | jsonbobject_agg(v, k) -+--++--+-- 1 | {c,a} | c ~ b ~ a | ["c", "a"] | {"a": 1, "b": 2, "c": 3} 2 | {f,e,d} | f ~ d | ["f", "e", "d"] | {"d": 4, "f": 6} ``` As promised, the result produced by `jsonbobjectagg()` is insensitive to order. Try this: ```plpgsql select class, (arrayagg(v) filter (where v <> 'b') over w) as "arrayagg(v)", (stringagg(v, ' ~ ') filter (where v <> 'b') over w) as "stringagg(v)", (jsonbagg(v) filter (where v <> 'b') over w) as "stringagg(v)", (jsonbobjectagg(v, k) filter (where v <> 'e') over w) as "jsonbobjectagg(v, k)" from t window w as ( partition by class order by k desc range between unbounded preceding and current row) order by 1; ``` This is the result: ``` class | arrayagg(v) | stringagg(v) | stringagg(v) | jsonbobject_agg(v, k) -+--++--+-- 1 | {c} | c | ["c"] | {"c": 3} 1 | {c} | c | ["c"] | {"b": 2, "c": 3} 1 | {c,a} | c ~ a | ["c", "a"] | {"a": 1, "b": 2, "c": 3} 2 | {f} | f | ["f"] | {"f": 6} 2 | {f,e} | f ~ e | ["f", "e"] | {"f": 6} 2 | {f,e,d} | f ~ e ~ d | ["f", "e", "d"] | {"d": 4, "f": 6} ```