Postgres - aggregate two columns into one item
You can concatenate the values together prior to feeding them into the array_agg()
function:
SELECT user_id, array_agg('[' || friend_id || ',' || confirmed || ']') as friends
FROM friends_map
WHERE user_id = 1
GROUP BY user_id
Demo: SQL Fiddle
How to group multiple columns into a single array or similar?
(t.id, t.tag_name, t.tag_color)
is short syntax for ROW(t.id, t.tag_name, t.tag_color)
- and a ROW constructor does not preserve nested attribute names. The manual:
By default, the value created by a
ROW
expression is of an anonymous record type. If necessary, it can be cast to a named composite type —
either the row type of a table, or a composite type created withCREATE TYPE AS
.
Bold emphasis mine. To also get proper key names in the result, cast to a registered composite type as advised in the quote, use a nested subselect, or simply use json_build_object()
in Postgres 9.4 or newer (effectively avoiding the ROW constructor a priori):
SELECT trm.target_record_id
, json_agg(json_build_object('id', t.id
, 'tag_name', t.tag_name
, 'tag_color', t.tag_color)) AS tags
FROM tags_record_maps trm
JOIN tags t USING (site_id)
WHERE t.id = trm.tag_id
GROUP BY trm.target_record_id
HAVING count(*) > 1;
I use original column names, but you can chose your key names freely. In your case:
json_agg(json_build_object('id', t.id
, 'name', t.tag_name
, 'color', t.tag_color)) AS tags
Detailed explanation:
- Return multiple columns of the same row as JSON array of objects
How to aggregate values in two columns in multiple records into one
You can unpivot and aggregate:
select firstname, lastname, string_agg(pt, ', ') as points
from (select t.*, v.pt,
row_number() over (partition by firstname, lastname, pt order by pt) as seqnum
from t cross apply
(values (t.startpoint), (t.endpoint)) as v(pt)
) t
where seqnum = 1
group by firstname, lastname;
Unfortunately, string_agg()
doesn't support distinct
. However, this is easily remedied by using row_number()
.
Edit:
If you wanted to identify each separate connected component, then you can use a recursive CTE:
with cte as (
select id, firstname, lastname,
convert(varchar(max), concat(startpoint, ', ', endpoint)) as points,
endpoint
from t
where not exists (select 1 from t t2 where t2.endpoint = t.startpoint)
union all
select cte.id, cte.firstname, cte.lastname,
concat(cte.point, ', ', cte.endpoint), t.endpoint
from cte join
t
on t.startpoint = cte.endpoint and t.id = cte.id
)
select *
from cte;
Here is a db<>fiddle.
How to aggregate two PostgreSQL columns to an array separated by brackets
Create an array from the two columns, the aggregate the array:
select id, array_agg(array[x,y])
from the_table
group by id;
Note that the default text representation of arrays uses curly braces ( {..}
) not square brackets ([..]
)
Aggregate functions across multiple columns in postgres
With a subquery you have all rows at your disposal:
SELECT sum(val) FROM (
SELECT unnest(array[a1,a2,a3]) as val FROM table) alias;
You can also group your rows, for example:
SELECT field, sum(val) FROM (
SELECT field, unnest(array[a1,a2,a3]) as val FROM table) alias
GROUP BY field;
Aggregate key column and multiple value columns to JSON object
Your query should be:
SELECT
name,
json_object_agg(key, json_build_object('x', x, 'y', y))
FROM data
GROUP BY name
demo:db<>fiddle
json_object_agg
does exactly what you want.
More efficient way to aggregate results in one table when grouping by different columns in SQL
You can LEFT JOIN
the results of the two separate aggregation queries, using the two columns id
and category
:
SELECT * FROM
(SELECT
id,
category,
subcategory,
AVG(value1) AS avgvalue1,
AVG(value2) AS avgvalue2
FROM your_table
GROUP BY 1, 2, 3)
LEFT JOIN
(SELECT
id,
category,
AVG(value0) AS avgvalue0
FROM your_table
GROUP BY 1, 2)
USING (id, category)
Related Topics
Update Values in Identity Column
How to Make a Table Read Only in SQL Server
SQL Server 2005 Using Dateadd to Add a Day to a Date
SQL Select Max(Date) and Corresponding Value
Equals(=) VS. Like for Date Data Type
Counting Rows for All Tables at Once
Select Random Row for Each Group
SQL Injection After Removing All Single-Quotes and Dash-Characters
SQL Server 2005, Turn Columns into Rows
How to Drop All Foreign Key Constraints in All Tables
How to Exclude Records with Certain Values in SQL Select
What Is the Data Type for Unix_Timestamp (Mysql)
"Merge" Style Operation with Literal Values
Calculate Number of Concurrent Events in SQL
Custom Order by to Ignore 'The'
Difference Between N'String' VS U'String' Literals in Oracle