【问题标题】:Concatenate rows in function PostgreSQL连接函数 PostgreSQL 中的行
【发布时间】:2021-04-05 09:35:57
【问题描述】:

假设有一个表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($1) p; 
$$ 
LANGUAGE PLpgSQL; 

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

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

【问题讨论】:

    标签: sql postgresql plpgsql


    【解决方案1】:

    你不需要 PL/pgSQL。

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

    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

    【讨论】:

      【解决方案2】:

      一个简单的查询:

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

      PostgreSQL fiddle

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-16
        • 1970-01-01
        • 2017-11-26
        • 2019-11-20
        • 1970-01-01
        • 2016-09-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多