PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Изберете динамичен набор от колони от таблица и получете сумата за всяка

Тази заявка създава пълния DML оператор, който търсите:

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;

Можете да го изпълните отделно или да обвиете тази заявка във функция plpgsql и да изпълните заявката автоматично с EXECUTE :

Пълна автоматизация

Тествано с 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;

Обаждане:

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

Връща:

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

Обяснете

Трудността е да се дефинира RETURN тип за функцията, докато броят и имената на върнатите колони ще варират. Една подробност, която помага малко:искате само integer колони.

Реших това, като формирах масив от bigint (sum(int_col) връща bigint ). Освен това връщам масив от имена на колони. И двете сортирани по азбучен ред по име на колона.

В извикването на функцията разделих тези масиви с unnest() стигайки до показания красив формат.

Динамично създадената и изпълнена заявка е нещо за напреднали. Не се обърквайте от множество слоеве цитати. По принцип имате EXECUTE който приема текстов аргумент, съдържащ SQL заявката за изпълнение. Този текст от своя страна се предоставя от вторична SQL заявка, която изгражда низа на заявката на първичната заявка.

Ако това е твърде много наведнъж или plpgsql е доста ново за вас, започнете с този свързан отговор където обяснявам основите, занимавайки се с много по-проста функция и предоставям връзки към ръководството за основните функции.

Ако производителност от съществено значение е директно запитване до каталога на Postgres (pg_catalog.pg_attributes ), вместо да използвате стандартизираните (но бавни) information_schema.columns . Ето един прост пример с pg_attributes .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Не може да завърши Flask-Migration

  2. Как да използвате Postgres any-клаузата с естествени заявки за JPA/Hibernate (параметри на масив)

  3. pg_dump при грешка в базата данни „извън споделената памет“

  4. маркиран потребител с етикет по време за всеки месец

  5. Как да конвертирам дата и време в стойност на епохата на unix в Postgres?