在函数 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
- 注意:尽量不要使用保留字符串(例如
end
、name
、start
等)来命名您的列.虽然 PostgreSQL 允许您使用它们,但它被认为是一种不好的做法。
演示:db<>fiddle
有点简单的查询:
select
name,
string_agg( concat(location, ', ', team_id, ', ', start, '-', "end"), E'\n') AS records
FROM t
group by name;
假设有一个 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
- 注意:尽量不要使用保留字符串(例如
end
、name
、start
等)来命名您的列.虽然 PostgreSQL 允许您使用它们,但它被认为是一种不好的做法。
演示:db<>fiddle
有点简单的查询:
select
name,
string_agg( concat(location, ', ', team_id, ', ', start, '-', "end"), E'\n') AS records
FROM t
group by name;