如何在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;
相關文章
相關標籤/搜索