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

Vælg rækkeceller som nye kolonner

Dette spørgsmål var meget sværere at løse, end du måske havde forventet. Dit forsøg med crosstab() sigtede i den rigtige retning. Men for at tildele dynamiske kolonnenavne skal du desuden bruge dynamisk SQL:EXECUTE i en plpgsql-funktion.

Skift datatypen for kolonnen infos.type fra text til regtype for at forhindre SQL-injektion og andre fejl. For eksempel har du datatypen number , som ikke er en gyldig PostgreSQL-datatype. Jeg erstattede den med numeric , så det kan fungere.

Du kunne forenkle opgaven ved at undgå kolonnenavne, der kræver dobbeltcitering. Ligesom nume_anterior i stedet for "nume anterior" .

Du vil måske tilføje en kolonne row_id til din tabel info_data for at markere alle elementer i en række. Du skal bruge det til crosstab() funktion, og det giver dig mulighed for at ignorere kolonner med NULL værdier. crosstab() funktion med to parametre kan håndtere manglende kolonner. Jeg syntetiserer den manglende kolonne med udtrykket (d.id-1)/13 nedenfor - hvilket virker for dataene i dit eksempel.

Du skal installere ekstra modul tablefunc (én gang pr. database):

CREATE EXTENSION tablefunc;

Find yderligere forklaring og links i dette relaterede svar .

Denne funktion vil gøre det, du leder 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 til:

SELECT * FROM x.mytbl();

Bliv ikke forvirret af den indlejrede notering i dollar .

BTW:Jeg oprettede kolonnelisten med denne erklæring:

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


  1. MySQL starter ikke efter at have ændret min.cf

  2. Django OperationalError:kunne ikke fordele ny proces til forbindelse

  3. Indsætter post i MySQL-database ved hjælp af C#

  4. MySQL FULLTEXT indekser problem