sql >> Databasteknik >  >> RDS >> PostgreSQL

Välj en dynamisk uppsättning kolumner från en tabell och få summan för varje

Den här frågan skapar den fullständiga DML-satsen du är ute 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 köra den separat eller slå in den här frågan i en plpgsql-funktion och köra frågan automatiskt med EXECUTE :

Full automatisering

Testad 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:

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

Returnerar:

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

Förklara

Svårigheten är att definiera RETURN typ för funktionen, medan antal och namn på kolumner som returneras kommer att variera. En detalj som hjälper lite:du vill bara ha integer kolumner.

Jag löste detta genom att bilda en array av bigint (sum(int_col) returnerar bigint ). Dessutom returnerar jag en rad kolumnnamn. Båda sorterade alfabetiskt efter kolumnnamn.

I funktionsanropet delade jag upp dessa arrayer med unnest() anländer till det stiliga formatet som visas.

Den dynamiskt skapade och körda frågan är avancerade saker. Bli inte förvirrad av flera lager av citat. I grund och botten har du EXECUTE som kräver ett textargument som innehåller SQL-frågan för att köras. Denna text tillhandahålls i sin tur av sekundär SQL-fråga som bygger frågesträngen för den primära frågan.

Om detta är för mycket på en gång eller plpgsql är ganska nytt för dig, börja med det här relaterade svaret där jag förklarar grunderna för en mycket enklare funktion och ger länkar till manualen för de viktigaste funktionerna.

Om prestanda är viktigt att fråga Postgres-katalogen direkt (pg_catalog.pg_attributes ) istället för att använda de standardiserade (men långsamma) information_schema.columns . Här är ett enkelt exempel med pg_attributes .




  1. Gruppera för månad inklusive tomma månader

  2. T-SQL Hoppa över Ta lagrad procedur

  3. PDO får bråkdelar av sekunder från Postgres

  4. MySQl, slå samman/sammanfoga 2 tabeller utan delad kolumn och ordning efter en gemensam kolumn