it-swarm.com.de

Postgres - Zeilen in Spalten transponieren

Die folgende Tabelle enthält mehrere E-Mail-Adressen für jeden Benutzer.

enter image description here

Ich muss dies auf Spalten in einer Benutzerabfrage reduzieren. Um mir die "neuesten" 3 E-Mail-Adressen basierend auf dem Erstellungsdatum zu geben.

user.name | user.id | email1          | email2           | email3**

Mary      | 123     | [email protected]  | [email protected] | [email protected]

Joe       | 345     | [email protected]   | [NULL]           | [NULL]
33
dacology

Verwenden Sie crosstab() aus dem tablefunc Modul.

SELECT * FROM crosstab(
   $$SELECT user_id, user_name, rn, email_address
     FROM  (
        SELECT u.user_id, u.user_name, e.email_address
             , row_number() OVER (PARTITION BY u.user_id
                            ORDER BY e.creation_date DESC NULLS LAST) AS rn
        FROM   usr u
        LEFT   JOIN email_tbl e USING (user_id)
        ) sub
     WHERE  rn < 4
     ORDER  BY user_id
   $$
  , 'VALUES (1),(2),(3)'
   ) AS t (user_id int, user_name text, email1 text, email2 text, email3 text);

Ich habe für den ersten Parameter Dollar-Anführungszeichen verwendet, was keine besondere Bedeutung hat. Es ist nur praktisch, wenn Sie einfache Anführungszeichen in der Abfragezeichenfolge umgehen müssen, was häufig der Fall ist:

Detaillierte Erklärung und Anleitung hier:

Und insbesondere für "zusätzliche Spalten":

Die besonderen Schwierigkeiten sind hier:

  • Das Fehlen von Schlüsselnamen.
    -> In einer Unterabfrage ersetzen wir durch row_number() .

  • Die unterschiedliche Anzahl von E-Mails.
    -> Wir beschränken uns auf eine max. von drei im äußeren SELECT
    und verwenden Sie crosstab() mit zwei Parametern und geben Sie eine Liste der möglichen Tasten an.

Achten Sie auf NULLS LAST In ORDER BY .

44

Wenn jemand diese Frage findet und eine dynamische Lösung dafür benötigt, bei der Sie eine undefinierte Anzahl von Spalten transponieren müssen und nicht genau 3, können Sie hier eine gute Lösung finden: https://github.com/ jumpstarter-io/colpivot

12

der obige Code hat mir wirklich geholfen. Jetzt versuche ich, der Pivot-Tabelle weitere Felder hinzuzufügen.

    SELECT * INTO temp_pivot_table FROM crosstab(
    $$SELECT lead_id, magazine_id, days_between_mailers, rn
    FROM  (
    SELECT u.lead_id, u.magazine_id, u.days_between_mailers
         , row_number() OVER (PARTITION BY u.lead_id
                        ORDER BY u.id ASC NULLS LAST) AS rn
    FROM   temp_mailer_stats u
    ) sub
    WHERE  rn <= 3
    ORDER  BY lead_id
   $$

  , 'VALUES (1),(2),(3),(4),(5),(6)'
  ) AS t (lead_id int, magazine1 text, magazine2 text, magazine3 text, 
   days_between1 integer, days_between2 integer, days_between3 integer);

Natürlich kann ich separate Tabellen erstellen und diese dann zusammenfügen, aber wenn ich einen Schritt speichern kann, wäre das ideal.

Vielen Dank im Voraus für die Hilfe.

0
ja11946