sql >> Databáze >  >> RDS >> PostgreSQL

Vyberte buňky řádku jako nové sloupce

Tato otázka byla mnohem těžší vyřešit, než jste možná čekali. Váš pokus s crosstab() mířil správným směrem. Ale k přiřazení dynamických názvů sloupců potřebujete navíc dynamické SQL:EXECUTE ve funkci plpgsql.

Změňte datový typ sloupce infos.type z text na regtype aby se zabránilo vkládání SQL a dalším chybám. Máte například datový typ number , což není platný datový typ PostgreSQL. Nahradil jsem jej numeric , takže to může fungovat.

Mohli byste zjednodušte úlohu tím, že se vyhnete názvům sloupců, které vyžadují dvojité uvozovky. Jako nume_anterior místo "nume anterior" .

Možná budete chtít přidat sloupec row_id do vaší tabulky info_data pro označení všech prvků jednoho řádku. Potřebujete jej pro crosstab() a umožňuje vám ignorovat sloupce s NULL hodnoty. crosstab() funkce se dvěma parametry si dokáže poradit s chybějícími sloupci. Chybějící sloupec syntetizuji výrazem (d.id-1)/13 níže – což funguje pro data ve vašem příkladu.

Je třeba nainstalovat přídavný modul tablefunc (jednou pro databázi):

CREATE EXTENSION tablefunc;

Najděte další vysvětlení a odkazy v této související odpovědi .

Tato funkce udělá to, co hledáte:

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

Volejte:

SELECT * FROM x.mytbl();

Nenechte se zmást vnořeným dolarové kotace .

BTW:Vytvořil jsem seznam sloupců s tímto prohlášením:

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


  1. Vnitřní části sedmi druhů SQL Server – část 2

  2. Alternativy MySQL Proxy pro sdílení databáze

  3. Odstranění výchozího trasování – část 1

  4. Vícenásobné a jednotlivé indexy