sql >> Database >  >> RDS >> PostgreSQL

Selecteer rijcellen als nieuwe kolommen

Deze vraag was een stuk moeilijker oplossen dan je misschien had verwacht. Uw poging met crosstab() in de goede richting mikte. Maar om dynamische kolomnamen toe te wijzen heb je daarnaast dynamische SQL nodig:EXECUTE in een plpgsql-functie.

Wijzig het gegevenstype van de kolom infos.type van text naar regtype om SQL-injectie en andere fouten te voorkomen. U hebt bijvoorbeeld het gegevenstype number , wat geen geldig PostgreSQL-gegevenstype is. Ik heb het vervangen door numeric , zodat het kan werken.

Je zou vereenvoudig de taak door kolomnamen te vermijden die dubbele aanhalingstekens nodig hebben. Zoals nume_anterior in plaats van "nume anterior" .

Misschien wilt u een kolom row_id . toevoegen naar uw tabel info_data om alle elementen van één rij te markeren. Je hebt het nodig voor de crosstab() functie, en u kunt kolommen negeren met NULL waarden. De crosstab() functie met twee parameters kan omgaan met ontbrekende kolommen. Ik synthetiseer de ontbrekende kolom met de uitdrukking (d.id-1)/13 hieronder - wat werkt voor de gegevens in uw voorbeeld.

U moet de aanvullende module tablefunc installeren (eenmaal per database):

CREATE EXTENSION tablefunc;

Zoek aanvullende uitleg en links in dit gerelateerde antwoord .

Deze functie doet wat je zoekt:

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$;

Bel:

SELECT * FROM x.mytbl();

Raak niet in de war door de geneste dollarcitaten .

BTW:ik heb de kolomlijst gemaakt met deze verklaring:

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


  1. JSON_LENGTH() – Retourneert de lengte van een JSON-document in MySQL

  2. Sla de uitvoer van mysql-query's op in een shell-variabele

  3. MySQL waarom cursor.execute(sql, multi=True) niet werkt, maar 2 cursor.execute(sql) wel?

  4. Ik wil invoegen met mikro-orm, maar het vindt mijn tabel niet:c (TableNotFoundException)