Reputation: 241
I want to aggregate rows using the string aggregate function, however one column is an array.
I have three columns: Employee, Year, Grades. The column Grade is an array. Example:
Row (1) : Employee: Tom | Year: 2019 | Grades: 11,33
Row (2) : Employee: Tom | Year: 2018 | Grades: 45,24,54
'Grade' column is an array. It represents grades for the different tests he took that year
select
Employee,
string_agg (distinct Year, ','),
string_agg (distinct Grades, ',')
from Employee_grades
group by 1
ERROR:
function string_agg(bigint[], unknown) does not exist Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Upvotes: 2
Views: 11325
Reputation: 1269443
If you don't really care about removing duplicates, you can convert to a string using array_to_string()
:
select employee, array_agg(distinct year),
string_agg(array_to_string(grades, ','), ',')
from (values ('Tom', 2019, array[11, 33]),
('Tom', 2018, array[10, 20, 30])
) v(employee, year, grades)
group by employee;
If you actually want to remove duplicates, this is a bit trickier. Unnesting and de-duping may be the only approach:
with t as (
select *
from (values ('Tom', 2019, array[11, 33]),
('Tom', 2018, array[11, 20, 30])
) v(employee, year, grades)
)
select t.*,
(select array_agg(distinct grade)
from t t2 cross join lateral
unnest(grades) grade
where t2.employee = t.employee
) as grades
from (select employee, array_agg(distinct year) as year
from t
group by t.employee
) t;
I prefer to leave the results as arrays, but the results can easily be converted to strings if you prefer.
Upvotes: 4
Reputation: 175556
You should use casting:
select Employee,
string_agg(distinct Year::text, ','),
string_agg(distinct Grades::text, ',')
from Employee_grades
group by Employee -- GROUP BY 1 is a bad practice
Upvotes: 4