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

Vyberte dynamickou sadu sloupců z tabulky a získejte součet pro každý z nich

Tento dotaz vytvoří úplný příkaz DML, který hledáte:

WITH x AS (
   SELECT 'public'::text     AS _schema  -- provide schema name ..
         ,'somereport'::text AS _tbl     -- .. and table name once
   )
SELECT 'SELECT ' || string_agg('sum(' || quote_ident(column_name)
                 || ') AS sum_' || quote_ident(column_name), ', ')
       || E'\nFROM   ' || quote_ident(x._schema) || '.' || quote_ident(x._tbl)
FROM   x, information_schema.columns
WHERE  table_schema = _schema
AND    table_name = _tbl
AND    data_type = 'integer'
GROUP  BY x._schema, x._tbl;

Můžete jej spustit samostatně nebo tento dotaz zabalit do funkce plpgsql a spustit dotaz automaticky pomocí EXECUTE :

Plná automatizace

Testováno s PostgreSQL 9.1.4

CREATE OR REPLACE FUNCTION f_get_sums(_schema text, _tbl text)
  RETURNS TABLE(names text[], sums bigint[]) AS
$BODY$
BEGIN

RETURN QUERY EXECUTE (
    SELECT 'SELECT ''{'
           || string_agg(quote_ident(c.column_name), ', ' ORDER BY c.column_name)
           || '}''::text[],
           ARRAY['
           || string_agg('sum(' || quote_ident(c.column_name) || ')'
                                                   , ', ' ORDER BY c.column_name)
           || ']
    FROM   '
           || quote_ident(_schema) || '.' || quote_ident(_tbl)
    FROM   information_schema.columns c
    WHERE  table_schema = _schema
    AND    table_name = _tbl
    AND    data_type = 'integer'
    );

END;
$BODY$
  LANGUAGE plpgsql;

Volejte:

SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM   f_get_sums('public', 'somereport');

Vrátí:

   name        | col_sum
---------------+---------
 int_col1      |    6614
 other_int_col |    8364
 third_int_col | 2720642

Vysvětlete

Obtížnost je definovat RETURN zadejte pro funkci, zatímco počet a názvy vrácených sloupců se budou lišit. Jeden detail, který trochu pomáhá:chcete pouze integer sloupce.

Vyřešil jsem to vytvořením pole bigint (sum(int_col) vrátí bigint ). Navíc vracím pole názvů sloupců. Oba jsou seřazeny abecedně podle názvu sloupce.

Ve volání funkce jsem tato pole rozdělil pomocí unnest() dorazíte k zobrazenému pěknému formátu.

Dynamicky vytvářený a prováděný dotaz je pokročilá záležitost. Nenechte se zmást více vrstvami uvozovek. V podstatě máte EXECUTE který vyžaduje ke spuštění textový argument obsahující dotaz SQL. Tento text zase poskytuje sekundární SQL dotaz, který vytváří řetězec dotazu primárního dotazu.

Pokud je toho příliš mnoho najednou nebo plpgsql je pro vás poměrně nová, začněte touto související odpovědí kde vysvětlím základy práce s mnohem jednodušší funkcí a poskytnu odkazy na příručku pro hlavní funkce.

Pokud výkon je zásadní dotazovat se přímo v katalogu Postgres (pg_catalog.pg_attributes ) namísto použití standardizovaného (ale pomalého) information_schema.columns . Zde je jednoduchý příklad s pg_attributes .




  1. Jak vyřešit chybu Oracle ORA-01790?

  2. Rozdíl mezi RDBMS a ORDBMS

  3. Jak přidám řetězec s hodnotou automatického přírůstku na SQL Server?

  4. Kurz transakcí SQL