在函数 PostgreSQL 中连接行

Concatenate rows in function PostgreSQL

假设有一个 table projects 包含项目名称、位置、团队 ID、开始和结束年份。如何连接行以便相同的名称将其他信息组合成一个字符串?

name        location       team_id      start       end 
Library     Atlanta        2389         2015        2017
Library     Georgetown     9920         2003        2007
Museum      Auckland       3092         2005        2007

预期输出如下所示:

name                 Records 
Library     Atlanta, 2389, 2015-2017
            Georgetown, 9920, 2003-2007
Museum      Auckland, 3092, 2005-2007

每行应包含行尾/换行符。

我有这个功能,但我认为仅使用 CONCAT 是行不通的。还有什么其他方法可以做到这一点?我尝试了什么:

CREATE OR REPLACE TYPE projects (name TEXT, records TEXT); 

CREATE OR REPLACE FUNCTION records (INT) 
RETURNS SETOF projects AS
$$ 
     RETURN QUERY
     SELECT p.name
            CONCAT(p.location, ', ', p.team_id, ', ', p.start, '-', p.end, CHAR(10))
     FROM projects() p; 
$$ 
LANGUAGE PLpgSQL; 

我尝试使用 CHAR(10) 作为换行符,但出现语法错误(不知道为什么?)。

上面的示例连接了字符串,但预计会删除重复的名称。

你不需要 PL/pgSQL。

首先使用 DISTINCT 消除重复的 name,然后在子查询中您可以 concat 将列合并为一个字符串。之后使用 array_agg 从中创建一个数组。然后它将“合并”多个数组,以防子查询 returns 多于一行。最后,使用 array_to_string 去掉逗号和花括号。您可以简单地使用 E'\n'E 代表 escape),而不是使用换行符的字符值:

WITH j (name,location,team_id,start,end_) AS (
  VALUES ('Library','Atlanta',2389,2015,2017),
         ('Library','Georgetown',9920,2003,2007),
         ('Museum','Auckland',3092,2005,2007)
)
SELECT 
  DISTINCT q1.name,
  array_to_string(
  (SELECT array_agg(concat(location,', ',team_id,', ',start,'-', end_, E'\n'))
   FROM j WHERE name = q1.name),'') AS records
FROM j q1;

  name   |           records           
---------+----------------------------
 Library | Atlanta, 2389, 2015-2017   
         | Georgetown, 9920, 2003-2007
         | 
 Museum  | Auckland, 3092, 2005-2007  
  • 注意:尽量不要使用保留字符串(例如endnamestart等)来命名您的列.虽然 PostgreSQL 允许您使用它们,但它被认为是一种不好的做法。

演示:db<>fiddle

有点简单的查询:

select 
  name, 
  string_agg( concat(location, ', ', team_id, ', ', start, '-', "end"), E'\n') AS records 
FROM  t 
group by name;

PostgreSQL fiddle