sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur sammanfogar man strängar av ett strängfält i en PostgreSQL "gruppa efter"-fråga?

PostgreSQL 9.0 eller senare:

Modern Postgres (sedan 2010) har string_agg(expression, delimiter) funktion som kommer att göra exakt vad frågaren letade efter:

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

Postgres 9 lade också till möjligheten att ange en ORDER BY klausul i något aggregerat uttryck; annars måste du beställa alla dina resultat eller hantera en odefinierad order. Så du kan nu skriva:

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

PostgreSQL 8.4.x:

PostgreSQL 8.4 (2009) introducerade aggregatfunktionen array_agg(expression) som samlar in värdena i en array. Sedan array_to_string() kan användas för att ge önskat resultat:

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

PostgreSQL 8.3.x och äldre:

När denna fråga ursprungligen ställdes fanns det ingen inbyggd aggregatfunktion för att sammanfoga strängar. Den enklaste anpassade implementeringen (föreslagen av Vajda Gabo i detta e-postlistinlägg, bland många andra) är att använda den inbyggda textcat funktion (som ligger bakom || operatör):

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

Här är CREATE AGGREGATE dokumentation.

Detta limmar helt enkelt ihop alla strängarna, utan separator. För att få ett ", " infogat mellan dem utan att ha det i slutet, kanske du vill skapa din egen sammanfogningsfunktion och ersätta den med "textcat" ovan. Här är en jag satte ihop och testade 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;

Den här versionen kommer att mata ut ett komma även om värdet i raden är null eller tomt, så du får utdata så här:

a, b, c, , e, , g

Om du föredrar att ta bort extra kommatecken för att mata ut detta:

a, b, c, e, g

Lägg sedan till en ELSIF kolla till funktionen så här:

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;


  1. ogiltig bytesekvens för kodning av UTF8

  2. Hur man installerar och säkrar MariaDB på CentOS 7

  3. Hur kan jag återställa MySQL root-användarens fullständiga rättigheter?

  4. Oracle tar bort rader från flera tabeller