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

Vælg et dynamisk sæt af kolonner fra en tabel og få summen for hver

Denne forespørgsel opretter den komplette DML-sætning, du leder efter:

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;
 

Du kan udføre den separat eller indpakke denne forespørgsel i en plpgsql-funktion og køre forespørgslen automatisk med EXECUTE :

Fuld automatisering

Testet med 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;
 

Ring til:

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

Returnerer:

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

Forklar

Vanskeligheden er at definere RETURN type for funktionen, mens antal og navne på kolonner, der returneres, vil variere. En detalje, der hjælper lidt:du vil kun have integer kolonner.

Jeg løste dette ved at danne et array af bigint (sum(int_col) returnerer bigint ). Derudover returnerer jeg en række kolonnenavne. Begge sorteret alfabetisk efter kolonnenavn.

I funktionskaldet opdeler jeg disse arrays med unnest() ankommer til det flotte format, der vises.

Den dynamisk oprettede og udførte forespørgsel er avancerede ting. Bliv ikke forvirret af flere lag af citater. Grundlæggende har du EXECUTE der skal udføres af et tekstargument, der indeholder SQL-forespørgslen. Denne tekst leveres igen af ​​sekundær SQL-forespørgsel, der bygger forespørgselsstrengen for den primære forespørgsel.

Hvis dette er for meget på én gang eller plpgsql er ret nyt for dig, start med dette relaterede svar hvor jeg forklarer det grundlæggende om en meget enklere funktion og giver links til manualen for de vigtigste funktioner.

Hvis ydelse er vigtigt at forespørge Postgres-kataloget direkte (pg_catalog.pg_attributes ) i stedet for at bruge de standardiserede (men langsomme) information_schema.columns . Her er et simpelt eksempel med pg_attributes .




  1. Dvale Opret kriterier for at slutte sig til den samme tabel to gange - prøvet 2 tilgang med 2 forskelsfejl

  2. Tilpasset forespørgselssideinddeling Cakephp

  3. PHP-database Ugyldigt argument angivet for foreach()

  4. ORA-12560:TNS:protokoladapterfejl