PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come concatenare le stringhe di un campo stringa in una query "raggruppa per" PostgreSQL?

PostgreSQL 9.0 o successivo:

Modern Postgres (dal 2010) ha il string_agg(expression, delimiter) funzione che farà esattamente ciò che il richiedente stava cercando:

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

Postgres 9 ha anche aggiunto la possibilità di specificare un ORDER BY clausola in qualsiasi espressione aggregata; altrimenti devi ordinare tutti i tuoi risultati o occuparti di un ordine indefinito. Quindi ora puoi scrivere:

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

PostgreSQL 8.4.x:

PostgreSQL 8.4 (nel 2009) ha introdotto la funzione di aggregazione array_agg(expression) che raccoglie i valori in una matrice. Quindi array_to_string() può essere utilizzato per dare il risultato desiderato:

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

PostgreSQL 8.3.xe precedenti:

Quando questa domanda è stata originariamente posta, non esisteva una funzione di aggregazione incorporata per concatenare le stringhe. L'implementazione personalizzata più semplice (suggerita da Vajda Gabo in questo post della mailing list, tra molti altri) consiste nell'usare il textcat integrato funzione (che si trova dietro il || operatore):

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

Ecco il CREATE AGGREGATE documentazione.

Questo incolla semplicemente tutte le stringhe insieme, senza separatore. Per ottenere un ", " inserito tra di loro senza averlo alla fine, potresti voler creare la tua funzione di concatenazione e sostituirla con "textcat" sopra. Eccone uno che ho messo insieme e testato l'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;

Questa versione genererà una virgola anche se il valore nella riga è nullo o vuoto, quindi ottieni un output in questo modo:

a, b, c, , e, , g

Se preferisci rimuovere le virgole extra per l'output:

a, b, c, e, g

Quindi aggiungi un ELSIF controlla la funzione in questo modo:

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;