Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Minikel)我改进了功能,使其更加灵活和方便。我认为它也可能对其他人有用,特别是因为它只依赖于pg/plsql,不需要像其他erics工作的派生(即plpython)那样安装扩展。按照9.3.5进行测试,但也应至少达到9.2_Sql_Postgresql_Pivot - Fatal编程技术网

Minikel)我改进了功能,使其更加灵活和方便。我认为它也可能对其他人有用,特别是因为它只依赖于pg/plsql,不需要像其他erics工作的派生(即plpython)那样安装扩展。按照9.3.5进行测试,但也应至少达到9.2

Minikel)我改进了功能,使其更加灵活和方便。我认为它也可能对其他人有用,特别是因为它只依赖于pg/plsql,不需要像其他erics工作的派生(即plpython)那样安装扩展。按照9.3.5进行测试,但也应至少达到9.2,sql,postgresql,pivot,Sql,Postgresql,Pivot,改进: 处理包含空格的数据透视列名 处理多行标题列 处理数据透视单元格和非聚合数据透视单元格中的聚合函数(如果基础表/视图已经进行聚合,则最后一个参数可能是'sum(cellval)'和'cellval' 透视单元格的自动检测数据类型(不再需要将其传递给函数) 用途: SELECT get_crosstab_statement('table_to_pivot', ARRAY['rowname' [, <other_row_header_columns_as_well>], 'co

改进:

  • 处理包含空格的数据透视列名
  • 处理多行标题列
  • 处理数据透视单元格和非聚合数据透视单元格中的聚合函数(如果基础表/视图已经进行聚合,则最后一个参数可能是'sum(cellval)'和'cellval'
  • 透视单元格的自动检测数据类型(不再需要将其传递给函数)
用途:

SELECT get_crosstab_statement('table_to_pivot', ARRAY['rowname' [, <other_row_header_columns_as_well>], 'colname', 'max(cellval)');

这给了我一个线索,有东西存在,谢谢。另一个问题是,这不是完全动态的,例如,从交叉表(“…”)中选择*作为ct(行名称文本、类别1文本、类别2文本);我仍然需要手动输入ct(……)中的内容。我将尝试寻找更多的解决方案…这给了我一个线索,有些东西存在,谢谢。另一个问题是,这不是完全动态的,例如,从交叉表(“…”)中选择*作为ct(行名称文本、类别1文本、类别2文本);我仍然需要手动输入ct(……)中的内容。我将尝试寻找更多的解决方案…我正在尝试创建一个基于日期(数据类型:Date)标题的动态交叉表,即:产品,2016-01-312016-02-29 iPhone,2000000,400000 Android,150000,350000但是我得到了这个错误:
函数quote_ident(Date)不存在
,有什么想法吗?嗨,nospam,您是否也可以添加一个参数,用于将项目添加到where子句,如果没有参数使用默认值
where 1=1
?我正在尝试基于日期(数据类型:Date)头创建一个动态交叉表,即:Product,2016-01-312016-02-29 iPhone,2000000,400000 Android,150000,350000但是我得到了这个错误:
函数quote_ident(date)不存在
,有什么想法吗?嗨,nospam,你能不能也添加一个参数来向where子句添加项目,如果没有参数,使用默认值
其中1=1
CREATE TABLE food_fat (name character varying(20) NOT NULL, fat integer);
CREATE TABLE eaten (food character varying(20) NOT NULL, day date NOT NULL);
-- This view will be formatted as cross-table.
-- ORDER BY is important, otherwise crosstab won't merge rows
CREATE TEMPORARY VIEW mymeals AS 
       SELECT day,food,COUNT(*) AS meals FROM eaten 
       GROUP BY day, food ORDER BY day;
SELECT auto_crosstab_ordered('mymeals_cross',
      'mymeals', 'day', 'food', 'meals',  -- what table to convert to cross-table
      'food_fat', 'name', 'fat');         -- where to take the columns from
SELECT * FROM mymeals_cross;
    day     | bread | cheese | eggs 
------------+-------+--------+------
 2012-06-01 |     3 |      3 |    2
 2012-06-02 |     2 |      1 |    3
(2 rows)
-- FUNCTION get_col_type(tab, col)
-- returns the data type of column <col> in table <tab> as string
DROP FUNCTION get_col_type(TEXT, TEXT);
CREATE FUNCTION get_col_type(tab TEXT, col TEXT, OUT ret TEXT)
AS $BODY$ BEGIN
EXECUTE $f$
   SELECT atttypid::regtype::text
   FROM pg_catalog.pg_attribute
   WHERE attrelid='$f$||quote_ident(tab)||$f$'::regclass 
   AND attname='$f$||quote_ident(col)||$f$'
   $f$ INTO ret;
END;
$BODY$ LANGUAGE plpgsql;

-- FUNCTION get_crosstab_type(tab, row, val, cattab, catcol, catord)
--
-- This function generates the output type expression for the crosstab(text, text)
-- function from the PostgreSQL tablefunc module when the "categories" 
-- (cross table column labels) can be looked up in some view or table.
--
-- See auto_crosstab below for parameters
DROP FUNCTION get_crosstab_type(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT);
CREATE FUNCTION get_crosstab_type(tab TEXT, rw TEXT, val TEXT, cattab TEXT, 
       catcol TEXT, catord TEXT, OUT ret TEXT)
AS $BODY$ BEGIN
EXECUTE $f$
    SELECT '"$f$||quote_ident(rw)||$f$" $f$
                   ||get_col_type(quote_ident(tab), quote_ident(rw))||$f$'
           || string_agg(',"'||_values._v||'" $f$
                   ||get_col_type(quote_ident(tab), quote_ident(val))||$f$')
    FROM (SELECT DISTINCT ON(_t.$f$||quote_ident(catord)||$f$) _t.$f$||quote_ident(catcol)||$f$ AS _v
          FROM $f$||quote_ident(cattab)||$f$ _t
          ORDER BY _t.$f$||quote_ident(catord)||$f$) _values
    $f$ INTO ret;
END; $BODY$ LANGUAGE plpgsql;

-- FUNCTION auto_crosstab_ordered(view_name, tab, row, cat, val, cattab, catcol, catord)
--
-- This function creates a VIEW containing a cross-table of input table.
-- It fetches the column names of the cross table ("categories") from
-- another table.
--
-- view_name - name of VIEW to be created
-- tab - input table. This table / view must have 3 columns:
--   "row", "category", "value".
-- row - column name of the "row" column
-- cat - column name of the "category" column
-- val - column name of the "value" column
-- cattab - another table holding the possible categories
-- catcol - column name in cattab to use as column label in the cross table
-- catord - column name in cattab to sort columns in the cross table
DROP FUNCTION auto_crosstab_ordered(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT, TEXT, TEXT);
CREATE FUNCTION auto_crosstab_ordered(view_name TEXT, tab TEXT, rw TEXT,
    cat TEXT, val TEXT, cattab TEXT, catcol TEXT, catord TEXT) RETURNS void
AS $BODY$ BEGIN
EXECUTE $f$
CREATE VIEW $f$||quote_ident(view_name)||$f$ AS
  SELECT * FROM crosstab(
     'SELECT $f$||quote_ident(rw)||$f$,
         $f$||quote_ident(cat)||$f$,
         $f$||quote_ident(val)||$f$
     FROM $f$||quote_ident(tab)||$f$',
     'SELECT DISTINCT ON($f$||quote_ident(catord)||$f$) $f$||quote_ident(catcol)||$f$
      FROM $f$||quote_ident(cattab)||$f$ m 
      ORDER BY $f$||quote_ident(catord)||$f$'
     ) AS ($f$||get_crosstab_type(tab, rw, val, cattab, catcol, catord)||$f$)$f$;
END; $BODY$ LANGUAGE plpgsql;

-- FUNCTION auto_crosstab(view_name, tab, row, cat, val)
--
-- This function creates a VIEW containing a cross-table of input table.
-- It fetches the column names of the cross table ("categories") from
-- DISTINCT values of the 2nd column of the input table.
--
-- view_name - name of VIEW to be created
-- tab - input table. This table / view must have 3 columns:
--   "row", "category", "value".
-- row - column name of the "row" column
-- cat - column name of the "category" column
-- val - column name of the "value" column

DROP FUNCTION auto_crosstab(TEXT, TEXT, TEXT, TEXT, TEXT);
CREATE FUNCTION auto_crosstab(view_name TEXT, tab TEXT, rw TEXT, cat TEXT, val TEXT) RETURNS void
AS $$ BEGIN
    PERFORM auto_crosstab_ordered(view_name, tab, rw, cat, val, tab, cat, cat);
END; $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION public.pivotcode(tablename character varying, rowc character varying, colc character varying, cellc character varying, celldatatype character varying)

RETURNS character varying AS

$BODY$

declare

    dynsql1 varchar;
    dynsql2 varchar;
    columnlist varchar;

begin

    -- 1. retrieve list of column names.

    dynsql1 = 'select string_agg(distinct ''_''||'||colc||'||'' '||celldatatype||''','','' order by ''_''||'||colc||'||'' '||celldatatype||''') from '||tablename||';';
    execute dynsql1 into columnlist;

    -- 2. set up the crosstab query

    --create temp table temp as

    dynsql2 = 'select * from crosstab ( ''select '||rowc||','||colc||','||cellc||' from '||tablename||' group by 1,2 order by 1,2'', ''select distinct '||colc||' from '||tablename||' order by 1'' ) as newtable ( '||rowc||' varchar,'||columnlist||' );';

    return dynsql2;

 end

 $BODY$

  LANGUAGE plpgsql VOLATILE

  COST 100;
SELECT get_crosstab_statement('table_to_pivot', ARRAY['rowname' [, <other_row_header_columns_as_well>], 'colname', 'max(cellval)');
CREATE OR REPLACE FUNCTION get_crosstab_statement(tablename character varying, row_header_columns character varying[], pivot_headers_column character varying, pivot_values character varying)
  RETURNS character varying AS
$BODY$
--returns the sql statement to use for pivoting the table
--based on: http://www.cureffi.org/2013/03/19/automatically-creating-pivot-table-column-names-in-postgresql/
--based on: https://stackoverflow.com/questions/4104508/postgres-dynamic-column-headers-from-another-table
--based on: http://www.postgresonline.com/journal/categories/24-tablefunc

DECLARE
    arrayname CONSTANT character varying := 'r';

    row_headers_simple character varying;
    row_headers_quoted character varying;
    row_headers_castdown character varying;
    row_headers_castup character varying;
    row_header_count smallint;
    row_header record;

    pivot_values_columnname character varying;
    pivot_values_datatype character varying;
    pivot_headers_definition character varying;
    pivot_headers_simple character varying;

    sql_row_headers character varying;
    sql_pivot_headers character varying;
    sql_crosstab_result character varying;

BEGIN
    -- 1. create row header definitions
    row_headers_simple   :=         array_to_string(row_header_columns, ', ');
    row_headers_quoted   := '''' || array_to_string(row_header_columns, ''', ''') || '''';
    row_headers_castdown :=         array_to_string(row_header_columns, '::text, ') || '::text';

    row_header_count     := 0;
    sql_row_headers      := 'SELECT column_name, data_type
                            FROM information_schema.columns
                            WHERE table_name = ''' || tablename || ''' AND column_name IN (' || row_headers_quoted || ')';
    FOR row_header IN EXECUTE sql_row_headers LOOP
        row_header_count := row_header_count + 1;
        row_headers_castup := COALESCE(row_headers_castup || ', ', '') || arrayname || '[' || row_header_count || ']::' || row_header.data_type || ' AS ' || row_header.column_name;
    END LOOP;

    -- 2. retrieve basic column name in case an aggregate function is used
    SELECT coalesce(substring(pivot_values FROM '.*\((.*)\)'), pivot_values)
    INTO pivot_values_columnname;

    -- 3. retrieve pivot values datatype
    SELECT data_type
    FROM information_schema.columns
    WHERE table_name = tablename AND column_name = pivot_values_columnname
    INTO pivot_values_datatype;

    -- 4. retrieve list of pivot column names.
    sql_pivot_headers := 'SELECT string_agg(DISTINCT quote_ident(' || pivot_headers_column || '), '', '' ORDER BY quote_ident(' || pivot_headers_column || ')) as names, string_agg(DISTINCT quote_ident(' || pivot_headers_column || ') || '' ' || pivot_values_datatype || ''', '', '' ORDER BY quote_ident(' || pivot_headers_column || ') || '' ' || pivot_values_datatype || ''') as definitions FROM ' || tablename || ';';
    EXECUTE sql_pivot_headers INTO pivot_headers_simple, pivot_headers_definition;

    -- 5. set up the crosstab query
    sql_crosstab_result := 'SELECT  ' || replace (row_headers_castup || ', ' || pivot_headers_simple, ', ', ',
        ') || '
FROM    crosstab (
        ''SELECT ARRAY[' || row_headers_castdown || '] AS ' || arrayname || ', ' || pivot_headers_column || ', ' || pivot_values || '
        FROM ' || tablename || '
        GROUP BY ' || row_headers_simple || ', ' || pivot_headers_column || (CASE pivot_values_columnname=pivot_values WHEN true THEN ', ' || pivot_values ELSE '' END) || '
        ORDER BY ' || row_headers_simple || '''
    ,
        ''SELECT DISTINCT ' || pivot_headers_column || '
        FROM ' || tablename || '
        ORDER BY ' || pivot_headers_column || '''
    ) AS newtable (
        ' || arrayname || ' varchar[]' || ',
        ' || replace(pivot_headers_definition, ', ', ',
        ') || '
    );';

    RETURN sql_crosstab_result;
 END

 $BODY$
  LANGUAGE plpgsql STABLE
  COST 100;