如何在 SQL 中对数组进行 string_agg?

Posted

技术标签:

【中文标题】如何在 SQL 中对数组进行 string_agg?【英文标题】:How to string_agg an array in SQL? 【发布时间】:2019-09-10 15:09:12 【问题描述】:

我想使用字符串聚合函数聚合行,但是一列是一个数组。

我有三列:员工、年份、成绩。 Grade 列是一个数组。示例:

Row (1) : Employee: Tom | Year: 2019 | Grades: 11,33
Row (2) : Employee: Tom | Year: 2018 | Grades: 45,24,54

'Grade' 列是一个数组。它代表他当年参加的不同考试的成绩

select 
Employee, 
string_agg (distinct Year, ','),
string_agg (distinct Grades, ',')
from Employee_grades
group by 1

错误:

function string_agg(bigint[], unknown) 不存在 提示:否 函数匹配给定的名称和参数类型。你可能需要 添加显式类型转换。

【问题讨论】:

【参考方案1】:

你应该使用强制转换:

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

【讨论】:

谢谢。还要感谢您提到好的/坏的做法。帮助很大【参考方案2】:

如果您真的不关心删除重复项,您可以使用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;

如果您真的想删除重复项,这有点棘手。取消嵌套和重复数据删除可能是唯一的方法:

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;

我更喜欢将结果保留为数组,但如果您愿意,可以轻松地将结果转换为字符串。

【讨论】:

哇,这真的很有帮助。谢谢:)

以上是关于如何在 SQL 中对数组进行 string_agg?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server STRING_AGG() :在 Linq 中等效

2017 年之前 SQL Server 的 String_agg

2017 年之前 SQL Server 的 String_agg

在 SQL Server 中使用 STRING_AGG 获取唯一值

在 SQL Server 中使用 STRING_AGG 获取唯一值

SQL Server - 带有 string_agg 的索引视图