sql >> Databasteknik >  >> RDS >> PostgreSQL

Välj radceller som nya kolumner

Den här frågan var mycket svårare att lösa än du kanske har förväntat dig. Ditt försök med crosstab() siktade åt rätt håll. Men för att tilldela dynamiska kolumnnamn behöver du dessutom dynamisk SQL:EXECUTE i en plpgsql-funktion.

Ändra datatypen för kolumnen infos.type från text till regtype för att förhindra SQL-injektion och andra fel. Du har till exempel datatypen number , som inte är en giltig PostgreSQL-datatyp. Jag ersatte den med numeric , så det kan fungera.

Du kunde förenkla uppgiften genom att undvika kolumnnamn som behöver dubbla citat. Som nume_anterior istället för "nume anterior" .

Du kanske vill lägga till en kolumn row_id till din tabell info_data för att markera alla element i en rad. Du behöver den för crosstab() funktion, och den låter dig ignorera kolumner med NULL värden. crosstab() funktion med två parametrar kan hantera saknade kolumner. Jag syntetiserar den saknade kolumnen med uttrycket (d.id-1)/13 nedan - vilket fungerar för data i ditt exempel.

Du måste installera ytterligare modul tablefunc (en gång per databas):

CREATE EXTENSION tablefunc;

Hitta ytterligare förklaring och länkar i det här relaterade svaret .

Denna funktion kommer att göra vad du letar efter:

CREATE OR REPLACE FUNCTION f_mytbl()
  RETURNS TABLE (id int
, nume text           , prenume text       , cnp numeric
, "nume anterior" text, "stare civila" text, cetatenie text
, rezidenta text      , adresa text        , "tip act" text
, "serie ci" text     , "numar ci" text    , "data eliberarii" text
, "eliberat de" text)
  LANGUAGE plpgsql AS
$BODY$
BEGIN

RETURN QUERY EXECUTE $f$
SELECT *
FROM   crosstab(
    'SELECT (d.id-1)/13 -- AS row_id
          , i.id, d.value
     FROM   infos i
     JOIN   info_data d ON d.id_info = i.id
     ORDER  BY 1, i.id',

    'SELECT id
     FROM   infos
     ORDER  BY id'
    )
AS tbl ($f$ || 'id int,
, nume text           , prenume text       , cnp numeric
, "nume anterior" text, "stare civila" text, cetatenie text
, rezidenta text      , adresa text        , "tip act" text
, "serie ci" text     , "numar ci" text    , "data eliberarii" text
, "eliberat de" text)';

END;
$BODY$;

Ring:

SELECT * FROM x.mytbl();

Bli inte förvirrad av den kapslade notering i dollar .

BTW:Jag skapade kolumnlistan med detta uttalande:

SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
                              ,', ' ORDER BY i.id) 
FROM   infos i;


  1. Postgresql-partition och sqlalchemy

  2. Hur kan jag göra en primärnyckel som AUTOINCREMENT

  3. Lägg till varje värde till Ajax

  4. Mysql räkningsfrekvens