PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como concatenar strings de um campo de string em uma consulta PostgreSQL 'group by'?

PostgreSQL 9.0 ou posterior:


Postgres moderno (desde 2010) tem o string_agg(expression, delimiter) função que fará exatamente o que o solicitante estava procurando:
SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;

O Postgres 9 também adicionou a capacidade de especificar um ORDER BY cláusula em qualquer expressão agregada; caso contrário, você terá que ordenar todos os seus resultados ou lidar com uma ordem indefinida. Então agora você pode escrever:
SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;

PostgreSQL 8.4.x:


PostgreSQL 8.4 (em 2009) introduziu a função agregada array_agg(expression) que coleta os valores em uma matriz. Então array_to_string() pode ser usado para dar o resultado desejado:
SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;

PostgreSQL 8.3.xe anterior:


Quando esta questão foi colocada originalmente, não havia função agregada interna para concatenar strings. A implementação personalizada mais simples (sugerida por Vajda Gabo neste post da lista de discussão, entre muitos outros) é usar o textcat embutido função (que está por trás do || operador):
CREATE AGGREGATE textcat_all(
  basetype    = text,
  sfunc       = textcat,
  stype       = text,
  initcond    = ''
);

Aqui está o CREATE AGGREGATE documentação.

Isso simplesmente cola todas as cordas juntas, sem separador. Para obter um ", " inserido entre eles sem tê-lo no final, você pode querer fazer sua própria função de concatenação e substituí-la pelo "textcat" acima. Aqui está um que montei e testei em 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;

Esta versão produzirá uma vírgula mesmo que o valor na linha seja nulo ou vazio, então você obtém uma saída assim:
a, b, c, , e, , g

Se você preferir remover vírgulas extras para gerar isso:
a, b, c, e, g

Em seguida, adicione um ELSIF verifique a função assim:
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;