sql >> Database >  >> RDS >> PostgreSQL

Selecteer een dynamische set kolommen uit een tabel en ontvang de som voor elk

Deze query creëert de volledige DML-instructie die u zoekt:

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;

U kunt het afzonderlijk uitvoeren of deze query in een plpgsql-functie verpakken en de query automatisch uitvoeren met EXECUTE :

Volledige automatisering

Getest met 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;

Bel:

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

Retouren:

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

Uitleggen

De moeilijkheid is om de RETURN . te definiëren type voor de functie, terwijl het aantal en de namen van de geretourneerde kolommen zal variëren. Een detail dat een beetje helpt:je wilt alleen integer kolommen.

Ik heb dit opgelost door een array te vormen van bigint (sum(int_col) retourneert bigint ). Daarnaast retourneer ik een array met kolomnamen. Beide alfabetisch gesorteerd op kolomnaam.

In de functieaanroep heb ik deze arrays opgesplitst met unnest() aankomen op het mooie formaat dat wordt weergegeven.

De dynamisch gemaakte en uitgevoerde query is geavanceerd spul. Raak niet in de war door meerdere lagen aanhalingstekens. In principe heb je EXECUTE waarvoor een tekstargument nodig is dat de SQL-query bevat om uit te voeren. Deze tekst wordt op zijn beurt geleverd door een secundaire SQL-query die de queryreeks van de primaire query opbouwt.

Als dit teveel in één keer is of plpgsql is vrij nieuw voor u, begin met dit gerelateerde antwoord waar ik de basis uitleg over een veel eenvoudigere functie en links naar de handleiding voor de belangrijkste functies.

Als prestaties is essentieel om de Postgres-catalogus rechtstreeks te raadplegen (pg_catalog.pg_attributes ) in plaats van de gestandaardiseerde (maar trage) information_schema.columns . Hier is een eenvoudig voorbeeld met pg_attributes .




  1. AJAX Post Fatal Error-kolom kan niet nul zijn

  2. Schema instellen voor alle query's van een verbinding in psycopg2:racevoorwaarde ophalen bij het instellen van zoekpad

  3. update x set y =null duurt lang

  4. Hoe invoer-uitvoerparameters in SQL Server opgeslagen procedure/functie te declareren?