如何在PostgreSQL的“分组依据”查询中串联字符串字段的字符串?

我正在寻找一种经过查询来链接一个组内字段字符串的方法。 例如,我有一张桌子: php

ID   COMPANY_ID   EMPLOYEE
1    1            Anna
2    1            Bill
3    2            Carol
4    2            Dave

我想按company_id分组以获取相似信息: html

COMPANY_ID   EMPLOYEE
1            Anna, Bill
2            Carol, Dave

mySQL中有一个内置函数来执行此group_concat sql


#1楼

再次使用字符串链接的自定义聚合函数:您须要记住,select语句将以任何顺序放置行,所以您须要在from语句中使用order by子句进行子选择 ,而且而后使用带有group by子句的外部select来聚合字符串,所以: 数据库

SELECT custom_aggregate(MY.special_strings)
FROM (SELECT special_strings, grouping_column 
        FROM a_table 
        ORDER BY ordering_column) MY
GROUP BY MY.grouping_column

#2楼

如何使用Postgres内置数组函数? 至少在8.4上能够当即使用: express

SELECT company_id, array_to_string(array_agg(employee), ',')
FROM mytable
GROUP BY company_id;

#3楼

如前所述,建立本身的聚合函数是正确的事情。 这是个人串联聚合函数(您能够在法语中找到详细信息 ): 数组

CREATE OR REPLACE FUNCTION concat2(text, text) RETURNS text AS '
    SELECT CASE WHEN $1 IS NULL OR $1 = \'\' THEN $2
            WHEN $2 IS NULL OR $2 = \'\' THEN $1
            ELSE $1 || \' / \' || $2
            END; 
'
 LANGUAGE SQL;

CREATE AGGREGATE concatenate (
  sfunc = concat2,
  basetype = text,
  stype = text,
  initcond = ''

); app

而后将其用做: 函数

SELECT company_id, concatenate(employee) AS employees FROM ...

#4楼

我对这个答案不屑一顾,由于我通过一番搜索发现了它: post

我不知道的是PostgreSQL容许您使用CREATE AGGREGATE定义本身的聚合函数 测试

PostgreSQL列表上的该帖子显示了建立一个函数来执行所需的操做是多么简单:

CREATE AGGREGATE textcat_all(
  basetype    = text,
  sfunc       = textcat,
  stype       = text,
  initcond    = ''
);

SELECT company_id, textcat_all(employee || ', ')
FROM mytable
GROUP BY company_id;

#5楼

PostgreSQL 9.0或更高版本:

Postgres的最新版本(自2010年底开始)具备string_agg(expression, delimiter)函数,该函数将彻底执行问题的要求,甚至容许您指定分隔符字符串:

SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;

Postgres 9.0还增长了在任何聚合表达式中指定ORDER BY子句的功能; 不然,顺序是不肯定的。 所以,您如今能够编写:

SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;

或者确实是:

SELECT string_agg(actor_name, ', ' ORDER BY first_appearance)

PostgreSQL 8.4或更高版本:

PostgreSQL 8.4(2009年)引入了聚合函数array_agg(expression) ,该函数将值链接到一个数组中。 而后可使用array_to_string()给出所需的结果:

SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;

8.4版以前的版本的string_agg

若是有人遇到这种状况,但愿在9.0以前版本的数据库中找到兼容的填充程序,则能够在string_agg实现除ORDER BY子句之外的全部内容。

所以,使用如下定义,该方法应与9.x Postgres DB中的相同:

SELECT string_agg(name, '; ') AS semi_colon_separated_names FROM things;

但这将是语法错误:

SELECT string_agg(name, '; ' ORDER BY name) AS semi_colon_separated_names FROM things;
--> ERROR: syntax error at or near "ORDER"

已在PostgreSQL 8.3上测试。

CREATE FUNCTION string_agg_transfn(text, text, text)
    RETURNS text AS 
    $$
        BEGIN
            IF $1 IS NULL THEN
                RETURN $2;
            ELSE
                RETURN $1 || $3 || $2;
            END IF;
        END;
    $$
    LANGUAGE plpgsql IMMUTABLE
COST 1;

CREATE AGGREGATE string_agg(text, text) (
    SFUNC=string_agg_transfn,
    STYPE=text
);

自定义版本(全部Postgres版本)

在9.0以前,没有内置的聚合函数来链接字符串。 最简单的自定义实现( 由Vajda Gabo在此邮件列表中的建议中 ,以及其余不少建议)是使用内置的textcat函数(位于||运算符以后):

CREATE AGGREGATE textcat_all(
  basetype    = text,
  sfunc       = textcat,
  stype       = text,
  initcond    = ''
);

这是CREATE AGGREGATE文档。

这只是将全部琴弦粘在一块儿,没有分隔符。 为了使它们之间没有插入“,”,您可能想要建立本身的串联函数,并将其替换为上面的“ textcat”。 这是我整理并在8.3.12上测试过的一个:

CREATE FUNCTION commacat(acc text, instr text) RETURNS text AS $$
  BEGIN
    IF acc IS NULL OR acc = '' THEN
      RETURN instr;
    ELSE
      RETURN acc || ', ' || instr;
    END IF;
  END;
$$ LANGUAGE plpgsql;

即便该行中的值为null或为空,此版本也会输出逗号,所以您将得到以下输出:

a, b, c, , e, , g

若是您但愿删除多余的逗号以输出此内容:

a, b, c, e, g

而后将ELSIF检查添加到以下函数:

CREATE FUNCTION commacat_ignore_nulls(acc text, instr text) RETURNS text AS $$
  BEGIN
    IF acc IS NULL OR acc = '' THEN
      RETURN instr;
    ELSIF instr IS NULL OR instr = '' THEN
      RETURN acc;
    ELSE
      RETURN acc || ', ' || instr;
    END IF;
  END;
$$ LANGUAGE plpgsql;
相关文章
相关标签/搜索