Pivot

madlib Pivot函数的目的是提供一个数据汇聚工具能够在某张数据表上实现基本的OLAP类的操作,将汇总结果输出到另一张表中。

  1. pivot(
  2. source_table,
  3. output_table,
  4. index,
  5. pivot_cols,
  6. pivot_values,
  7. aggregate_func,
  8. fill_value,
  9. keep_null,
  10. output_col_dictionary
  11. )

参数

source_table

VARCHAR。需要将其中数据进行pivot的原表(视图)名。

output_table

VARCHAR。含有pivot输出结果数据的表名。输出表含有所有出现在’index’列表中的列。对每一个distinct值额外增加了列’pivot_cols’.

  1. Note:
  2. 输出表中的列名是自动生成的,具体请查看例子中是怎么实现的。惯例是使用以下字符串和分隔符下划线_来连接。
  3. * 值的列'pivot_values'的名称。
  4. * 聚合函数
  5. * pivot'pivot_cols'的名称
  6. * pivotl列中的值
index

VARCHAR,以逗号分隔的列,会形成输出pivot表的索引。通过index我们表明哪些值用来分组,它们是是pivot输出标的行。

pivot_cols

VARCHAR,逗号分隔的列,会组成pivotl输出表的列

pivot_values

VARCHAR.逗号分隔的列,包含了那些要被汇总的值

aggregate_func (optional)

VARCHAR,默认值‘AVG’,逗号分隔将被应用于数据的聚合函数的列表。他们可以使PostgreSQL内置的aggregate或者用户自定义的aggregate.它能够对于每一个列值传递一系列aggregate。详情请请参考例子12-14。

  1. Note
  2. 这里只允许只有具有严格转换函数的aggregate。一个严格的转换函数意味着包含null的韩会被忽略;该函数不被调用并且之前的状态值被保留。如果你对null输入需要其他形式,它需要在pivot函数调用之前完成。包含严格转换函数的aggregate在[2,3]中介绍。
fill_value (optional)

VARCHAR。默认NULL。如果被指定,将决定如何填充pivot操作结果的NULL值。这是一个全局参数(并不是应用于单个aggregate),并且应用post-aggregation到输出表上。

keep_null (optional)

BOOLEAN.默认值FALSE。如果是TRUE,会创建相当于NULL类别的pivot列。如果FALSE,对于NULL类别不会创建pivot列。

output_col_dictionary (optional)

BOOLEAN。默认值FALSE。这个参数用来处理自动生成列名超过PostgreSQL限制的63byte(可能会经常发生).如果为TRUE,列名会被设置为数字类型ID并且会创建一个词典表,表名为output_table的值+_dictionary后缀。如果是FALSE,会自动生成常规列名,除非超过了63byte限制。如果这样的话,会生成一个输出文件以及消息给用户。

Note:

  1. * index列中的NULL会被当做和其它值一样对待
  2. * pivot列中的NULL会被忽略除非设置keep_nullTRUE
  3. * 只有严格转换函数被允许,所以NULL会被忽略
  4. * 不允许在设置fill_value 参数的时候而没有设置keep_null参数,以防止可能出现的不确定性。为默认方式设置aggregate_funcNULL并且按照需要使用fill_value.
  5. * 不允许在设置output_col_dictionary参数的时候而不设置keep_null参数以避免可能的不确定性。为默认方式设置keep_nullNULL并且按照需要使用output_col_dictionary.
  6. * 表达式(而不是列名)不被支持,为需要的表达式创建一个视图并且将其作为一个输入表(看例子3)
  7. * aggregate_func参数允许传递一个部分映射(partial mapping)。缺值的列会被按照默认函数(average)聚合

例子

  1. 创建一个简单的数据集来演示基础pivot.
    1. DROP TABLE IF EXISTS pivset CASCADE; -- View below may depend on table so use CASCADE
    2. CREATE TABLE pivset(
    3. id INTEGER,
    4. piv INTEGER,
    5. val FLOAT8
    6. );
    7. INSERT INTO pivset VALUES
    8. (0, 10, 1),
    9. (0, 10, 2),
    10. (0, 20, 3),
    11. (1, 20, 4),
    12. (1, 30, 5),
    13. (1, 30, 6),
    14. (1, 10, 7),
    15. (NULL, 10, 8),
    16. (1, NULL, 9),
    17. (1, 10, NULL);
  2. 在这张表上执行pivot函数
    1. DROP TABLE IF EXISTS pivout;
    2. SELECT madlib.pivot('pivset', 'pivout', 'id', 'piv', 'val');
    3. SELECT * FROM pivout ORDER BY id;
    1. id | val_avg_piv_10 | val_avg_piv_20 | val_avg_piv_30
    2. ----+----------------+----------------+----------------
    3. 0 | 1.5 | 3 |
    4. 1 | 7 | 4 | 5.5
    5. | 8 | |
    这里NULL在输出中会显示为空。
    1. 现在我们增加更多的列到数据中并且创建一个视图。
      1. DROP VIEW IF EXISTS pivset_ext;
      2. CREATE VIEW pivset_ext AS
      3. SELECT *,
      4. COALESCE(id + (val / 3)::integer, 0) AS id2,
      5. COALESCE(100*(val / 3)::integer, 0) AS piv2,
      6. COALESCE(val + 10, 0) AS val2
      7. FROM pivset;
      8. SELECT id,id2,piv,piv2,val,val2 FROM pivset_ext
      9. ORDER BY id,id2,piv,piv2,val,val2;
      1. id | id2 | piv | piv2 | val | val2
      2. ----+-----+-----+------+-----+------
      3. 0 | 0 | 10 | 0 | 1 | 11
      4. 0 | 1 | 10 | 100 | 2 | 12
      5. 0 | 1 | 20 | 100 | 3 | 13
      6. 1 | 0 | 10 | 0 | | 0
      7. 1 | 2 | 20 | 100 | 4 | 14
      8. 1 | 3 | 10 | 200 | 7 | 17
      9. 1 | 3 | 30 | 200 | 5 | 15
      10. 1 | 3 | 30 | 200 | 6 | 16
      11. 1 | 4 | | 300 | 9 | 19
      12. | 0 | 10 | 300 | 8 | 18
      13. (10 rows)
    2. 我们使用另一个aggregate函数在刚才创建的视图上。
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv', 'val', 'sum');
      3. SELECT * FROM pivout ORDER BY id;
      1. id | val_sum_piv_10 | val_sum_piv_20 | val_sum_piv_30
      2. ----+----------------+----------------+----------------
      3. 0 | 3 | 3 |
      4. 1 | 7 | 4 | 11
      5. | 8 | |
    3. 现在创建一个自定义aggregate,注意这个aggregate必须有一个严格转换函数。
      1. DROP FUNCTION IF EXISTS array_add1 (ANYARRAY, ANYELEMENT) CASCADE;
      2. CREATE FUNCTION array_add1(ANYARRAY, ANYELEMENT) RETURNS ANYARRAY AS $$
      3. SELECT $1 || $2
      4. $$ LANGUAGE sql STRICT;
      5. DROP AGGREGATE IF EXISTS array_accum1 (anyelement);
      6. CREATE AGGREGATE array_accum1 (anyelement) (
      7. sfunc = array_add1,
      8. stype = anyarray,
      9. initcond = '{}'
      10. );
      11. DROP TABLE IF EXISTS pivout;
      12. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv', 'val', 'array_accum1');
      13. SELECT * FROM pivout ORDER BY id;
      1. id | val_array_accum1_piv_10 | val_array_accum1_piv_20 | val_array_accum1_piv_30
      2. ----+-------------------------+-------------------------+-------------------------
      3. 0 | {1,2} | {3} | {}
      4. 1 | {7} | {4} | {5,6}
      5. | {8} | {} | {}
    4. 在pivot列中保持null值。
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv', 'val', 'sum', True);
      3. SELECT * FROM pivout ORDER BY id;
      1. id | val_sum_piv_10 | val_sum_piv_20 | val_sum_piv_30 | val_sum_piv_null
      2. ----+----------------+----------------+----------------+------------------
      3. 0 | 3 | 3 | |
      4. 1 | 7 | 4 | 11 | 9
      5. | 8 | | |
    5. 使用预设的值来填充null结果
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv', 'val', 'sum', '111');
      3. SELECT * FROM pivout ORDER BY id;
      1. id | val_sum_piv_10 | val_sum_piv_20 | val_sum_piv_30
      2. ----+----------------+----------------+----------------
      3. 0 | 3 | 3 | 111
      4. 1 | 7 | 4 | 11
      5. | 8 | 111 | 111
    6. 使用多个index列。
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id,id2', 'piv', 'val');
      3. SELECT * FROM pivout ORDER BY id,id2;
      1. id | id2 | val_avg_piv_10 | val_avg_piv_20 | val_avg_piv_30
      2. ----+-----+----------------+----------------+----------------
      3. 0 | 0 | 1 | |
      4. 0 | 1 | 2 | 3 |
      5. 1 | 0 | | |
      6. 1 | 2 | | 4 |
      7. 1 | 3 | 7 | | 5.5
      8. 1 | 4 | | |
      9. | 0 | 8 | |
    7. 打开可读的扩展视图
      1. \x on
    8. 使用多个pivot列
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv, piv2', 'val');
      3. SELECT * FROM pivout ORDER BY id;
      1. -[ RECORD 1 ]-----------+----
      2. id | 0
      3. val_avg_piv_10_piv2_0 | 1
      4. val_avg_piv_10_piv2_100 | 2
      5. val_avg_piv_10_piv2_200 |
      6. val_avg_piv_10_piv2_300 |
      7. val_avg_piv_20_piv2_0 |
      8. val_avg_piv_20_piv2_100 | 3
      9. val_avg_piv_20_piv2_200 |
      10. val_avg_piv_20_piv2_300 |
      11. val_avg_piv_30_piv2_0 |
      12. val_avg_piv_30_piv2_100 |
      13. val_avg_piv_30_piv2_200 |
      14. val_avg_piv_30_piv2_300 |
      15. -[ RECORD 2 ]-----------+----
      16. id | 1
      17. val_avg_piv_10_piv2_0 |
      18. val_avg_piv_10_piv2_100 |
      19. val_avg_piv_10_piv2_200 | 7
      20. val_avg_piv_10_piv2_300 |
      21. val_avg_piv_20_piv2_0 |
      22. val_avg_piv_20_piv2_100 | 4
      23. val_avg_piv_20_piv2_200 |
      24. val_avg_piv_20_piv2_300 |
      25. val_avg_piv_30_piv2_0 |
      26. val_avg_piv_30_piv2_100 |
      27. val_avg_piv_30_piv2_200 | 5.5
      28. val_avg_piv_30_piv2_300 |
      29. ...
    9. 使用多个value列
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv', 'val, val2');
      3. SELECT * FROM pivout ORDER BY id;
      1. -[ RECORD 1 ]---+-----
      2. id | 0
      3. val_avg_piv_10 | 1.5
      4. val_avg_piv_20 | 3
      5. val_avg_piv_30 |
      6. val2_avg_piv_10 | 11.5
      7. val2_avg_piv_20 | 13
      8. val2_avg_piv_30 |
      9. -[ RECORD 2 ]---+-----
      10. id | 1
      11. val_avg_piv_10 | 7
      12. val_avg_piv_20 | 4
      13. val_avg_piv_30 | 5.5
      14. val2_avg_piv_10 | 8.5
      15. val2_avg_piv_20 | 14
      16. val2_avg_piv_30 | 15.5
      17. ...
    10. 在一个value列上使用多个aggregate函数(矢量积)
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv', 'val', 'avg, sum');
      3. SELECT * FROM pivout ORDER BY id;
      1. -[ RECORD 1 ]--+----
      2. id | 0
      3. val_avg_piv_10 | 1.5
      4. val_avg_piv_20 | 3
      5. val_avg_piv_30 |
      6. val_sum_piv_10 | 3
      7. val_sum_piv_20 | 3
      8. val_sum_piv_30 |
      9. -[ RECORD 2 ]--+----
      10. id | 1
      11. val_avg_piv_10 | 7
      12. val_avg_piv_20 | 4
      13. val_avg_piv_30 | 5.5
      14. val_sum_piv_10 | 7
      15. val_sum_piv_20 | 4
      16. val_sum_piv_30 | 11
      17. ...
    11. 对于不同的value列使用不同的aggregate函数
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv', 'val, val2',
      3. 'val=avg, val2=sum');
      4. SELECT * FROM pivout ORDER BY id;
      1. -[ RECORD 1 ]---+----
      2. id | 0
      3. val_avg_piv_10 | 1.5
      4. val_avg_piv_20 | 3
      5. val_avg_piv_30 |
      6. val2_sum_piv_10 | 23
      7. val2_sum_piv_20 | 13
      8. val2_sum_piv_30 |
      9. -[ RECORD 2 ]---+----
      10. id | 1
      11. val_avg_piv_10 | 7
      12. val_avg_piv_20 | 4
      13. val_avg_piv_30 | 5.5
      14. val2_sum_piv_10 | 17
      15. val2_sum_piv_20 | 14
      16. val2_sum_piv_30 | 31
      17. ...
    12. 对不同的value列使多个aggregate函数
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id', 'piv', 'val, val2',
      3. 'val=avg, val2=[avg,sum]');
      4. SELECT * FROM pivout ORDER BY id;
      1. -[ RECORD 1 ]---+-----
      2. id | 0
      3. val_avg_piv_10 | 1.5
      4. val_avg_piv_20 | 3
      5. val_avg_piv_30 |
      6. val2_avg_piv_10 | 11.5
      7. val2_avg_piv_20 | 13
      8. val2_avg_piv_30 |
      9. val2_sum_piv_10 | 23
      10. val2_sum_piv_20 | 13
      11. val2_sum_piv_30 |
      12. -[ RECORD 2 ]---+-----
      13. id | 1
      14. val_avg_piv_10 | 7
      15. val_avg_piv_20 | 4
      16. val_avg_piv_30 | 5.5
      17. val2_avg_piv_10 | 8.5
      18. val2_avg_piv_20 | 14
      19. val2_avg_piv_30 | 15.5
      20. val2_sum_piv_10 | 17
      21. val2_sum_piv_20 | 14
      22. val2_sum_piv_30 | 31
      23. ...
    13. 合并所有选项
      1. DROP TABLE IF EXISTS pivout;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id, id2', 'piv, piv2', 'val, val2',
      3. 'val=avg, val2=[avg,sum]', '111', True);
      4. SELECT * FROM pivout ORDER BY id,id2;
      1. -[ RECORD 1 ]--------------+-----
      2. id | 0
      3. id2 | 0
      4. val_avg_piv_null_piv2_0 | 111
      5. val_avg_piv_null_piv2_100 | 111
      6. val_avg_piv_null_piv2_200 | 111
      7. val_avg_piv_null_piv2_300 | 111
      8. val_avg_piv_10_piv2_0 | 1
      9. val_avg_piv_10_piv2_100 | 111
      10. val_avg_piv_10_piv2_200 | 111
      11. val_avg_piv_10_piv2_300 | 111
      12. val_avg_piv_20_piv2_0 | 111
      13. val_avg_piv_20_piv2_100 | 111
      14. val_avg_piv_20_piv2_200 | 111
      15. val_avg_piv_20_piv2_300 | 111
      16. val_avg_piv_30_piv2_0 | 111
      17. val_avg_piv_30_piv2_100 | 111
      18. val_avg_piv_30_piv2_200 | 111
      19. val_avg_piv_30_piv2_300 | 111
      20. val2_avg_piv_null_piv2_0 | 111
      21. val2_avg_piv_null_piv2_100 | 111
      22. val2_avg_piv_null_piv2_200 | 111
      23. val2_avg_piv_null_piv2_300 | 111
      24. val2_avg_piv_10_piv2_0 | 11
      25. val2_avg_piv_10_piv2_100 | 111
      26. val2_avg_piv_10_piv2_200 | 111
      27. val2_avg_piv_10_piv2_300 | 111
      28. val2_avg_piv_20_piv2_0 | 111
      29. val2_avg_piv_20_piv2_100 | 111
      30. val2_avg_piv_20_piv2_200 | 111
      31. val2_avg_piv_20_piv2_300 | 111
      32. val2_avg_piv_30_piv2_0 | 111
      33. val2_avg_piv_30_piv2_100 | 111
      34. val2_avg_piv_30_piv2_200 | 111
      35. val2_avg_piv_30_piv2_300 | 111
      36. val2_sum_piv_null_piv2_0 | 111
      37. val2_sum_piv_null_piv2_100 | 111
      38. val2_sum_piv_null_piv2_200 | 111
      39. val2_sum_piv_null_piv2_300 | 111
      40. val2_sum_piv_10_piv2_0 | 11
      41. val2_sum_piv_10_piv2_100 | 111
      42. val2_sum_piv_10_piv2_200 | 111
      43. val2_sum_piv_10_piv2_300 | 111
      44. val2_sum_piv_20_piv2_0 | 111
      45. val2_sum_piv_20_piv2_100 | 111
      46. val2_sum_piv_20_piv2_200 | 111
      47. val2_sum_piv_20_piv2_300 | 111
      48. val2_sum_piv_30_piv2_0 | 111
      49. val2_sum_piv_30_piv2_100 | 111
      50. val2_sum_piv_30_piv2_200 | 111
      51. val2_sum_piv_30_piv2_300 | 111
      52. -[ RECORD 2 ]--------------+-----
      53. id | 0
      54. id2 | 1
      55. val_avg_piv_null_piv2_0 | 111
      56. val_avg_piv_null_piv2_100 | 111
      57. val_avg_piv_null_piv2_200 | 111
      58. val_avg_piv_null_piv2_300 | 111
      59. val_avg_piv_10_piv2_0 | 111
      60. val_avg_piv_10_piv2_100 | 2
      61. val_avg_piv_10_piv2_200 | 111
      62. val_avg_piv_10_piv2_300 | 111
      63. val_avg_piv_20_piv2_0 | 111
      64. val_avg_piv_20_piv2_100 | 3
      65. val_avg_piv_20_piv2_200 | 111
      66. val_avg_piv_20_piv2_300 | 111
      67. val_avg_piv_30_piv2_0 | 111
      68. val_avg_piv_30_piv2_100 | 111
      69. val_avg_piv_30_piv2_200 | 111
      70. val_avg_piv_30_piv2_300 | 111
      71. val2_avg_piv_null_piv2_0 | 111
      72. val2_avg_piv_null_piv2_100 | 111
      73. val2_avg_piv_null_piv2_200 | 111
      74. val2_avg_piv_null_piv2_300 | 111
      75. val2_avg_piv_10_piv2_0 | 111
      76. val2_avg_piv_10_piv2_100 | 12
      77. val2_avg_piv_10_piv2_200 | 111
      78. val2_avg_piv_10_piv2_300 | 111
      79. val2_avg_piv_20_piv2_0 | 111
      80. val2_avg_piv_20_piv2_100 | 13
      81. val2_avg_piv_20_piv2_200 | 111
      82. val2_avg_piv_20_piv2_300 | 111
      83. val2_avg_piv_30_piv2_0 | 111
      84. val2_avg_piv_30_piv2_100 | 111
      85. val2_avg_piv_30_piv2_200 | 111
      86. val2_avg_piv_30_piv2_300 | 111
      87. val2_sum_piv_null_piv2_0 | 111
      88. val2_sum_piv_null_piv2_100 | 111
      89. val2_sum_piv_null_piv2_200 | 111
      90. val2_sum_piv_null_piv2_300 | 111
      91. val2_sum_piv_10_piv2_0 | 111
      92. val2_sum_piv_10_piv2_100 | 12
      93. val2_sum_piv_10_piv2_200 | 111
      94. val2_sum_piv_10_piv2_300 | 111
      95. val2_sum_piv_20_piv2_0 | 111
      96. val2_sum_piv_20_piv2_100 | 13
      97. val2_sum_piv_20_piv2_200 | 111
      98. val2_sum_piv_20_piv2_300 | 111
      99. val2_sum_piv_30_piv2_0 | 111
      100. val2_sum_piv_30_piv2_100 | 111
      101. val2_sum_piv_30_piv2_200 | 111
      102. val2_sum_piv_30_piv2_300 | 111
      103. ...
    14. 为输出列名创建一个字典
      1. DROP TABLE IF EXISTS pivout, pivout_dictionary;
      2. SELECT madlib.pivot('pivset_ext', 'pivout', 'id, id2', 'piv, piv2', 'val, val2',
      3. 'val=avg, val2=[avg,sum]', '111', True, True);
      4. SELECT * FROM pivout_dictionary;
      1. __pivot_cid__ | pval | agg | piv | piv2 | col_name
      2. ---------------+------+-----+-----+------+------------------------------
      3. __p_1__ | val | avg | | 100 | "val_avg_piv_null_piv2_100"
      4. __p_5__ | val | avg | 10 | 100 | "val_avg_piv_10_piv2_100"
      5. __p_9__ | val | avg | 20 | 100 | "val_avg_piv_20_piv2_100"
      6. __p_12__ | val | avg | 30 | 0 | "val_avg_piv_30_piv2_0"
      7. __p_16__ | val2 | avg | | 0 | "val2_avg_piv_null_piv2_0"
      8. __p_23__ | val2 | avg | 10 | 300 | "val2_avg_piv_10_piv2_300"
      9. __p_27__ | val2 | avg | 20 | 300 | "val2_avg_piv_20_piv2_300"
      10. __p_30__ | val2 | avg | 30 | 200 | "val2_avg_piv_30_piv2_200"
      11. __p_34__ | val2 | sum | | 200 | "val2_sum_piv_null_piv2_200"
      12. __p_38__ | val2 | sum | 10 | 200 | "val2_sum_piv_10_piv2_200"
      13. __p_41__ | val2 | sum | 20 | 100 | "val2_sum_piv_20_piv2_100"
      14. __p_45__ | val2 | sum | 30 | 100 | "val2_sum_piv_30_piv2_100"
      15. __p_2__ | val | avg | | 200 | "val_avg_piv_null_piv2_200"
      16. __p_6__ | val | avg | 10 | 200 | "val_avg_piv_10_piv2_200"
      17. __p_11__ | val | avg | 20 | 300 | "val_avg_piv_20_piv2_300"
      18. __p_15__ | val | avg | 30 | 300 | "val_avg_piv_30_piv2_300"
      19. __p_19__ | val2 | avg | | 300 | "val2_avg_piv_null_piv2_300"
      20. __p_20__ | val2 | avg | 10 | 0 | "val2_avg_piv_10_piv2_0"
      21. __p_24__ | val2 | avg | 20 | 0 | "val2_avg_piv_20_piv2_0"
      22. __p_28__ | val2 | avg | 30 | 0 | "val2_avg_piv_30_piv2_0"
      23. __p_33__ | val2 | sum | | 100 | "val2_sum_piv_null_piv2_100"
      24. __p_37__ | val2 | sum | 10 | 100 | "val2_sum_piv_10_piv2_100"
      25. __p_42__ | val2 | sum | 20 | 200 | "val2_sum_piv_20_piv2_200"
      26. __p_46__ | val2 | sum | 30 | 200 | "val2_sum_piv_30_piv2_200"
      27. __p_3__ | val | avg | | 300 | "val_avg_piv_null_piv2_300"
      28. __p_7__ | val | avg | 10 | 300 | "val_avg_piv_10_piv2_300"
      29. __p_10__ | val | avg | 20 | 200 | "val_avg_piv_20_piv2_200"
      30. __p_14__ | val | avg | 30 | 200 | "val_avg_piv_30_piv2_200"
      31. __p_18__ | val2 | avg | | 200 | "val2_avg_piv_null_piv2_200"
      32. __p_21__ | val2 | avg | 10 | 100 | "val2_avg_piv_10_piv2_100"
      33. __p_25__ | val2 | avg | 20 | 100 | "val2_avg_piv_20_piv2_100"
      34. __p_29__ | val2 | avg | 30 | 100 | "val2_avg_piv_30_piv2_100"
      35. __p_32__ | val2 | sum | | 0 | "val2_sum_piv_null_piv2_0"
      36. __p_36__ | val2 | sum | 10 | 0 | "val2_sum_piv_10_piv2_0"
      37. __p_43__ | val2 | sum | 20 | 300 | "val2_sum_piv_20_piv2_300"
      38. __p_47__ | val2 | sum | 30 | 300 | "val2_sum_piv_30_piv2_300"
      39. __p_0__ | val | avg | | 0 | "val_avg_piv_null_piv2_0"
      40. __p_4__ | val | avg | 10 | 0 | "val_avg_piv_10_piv2_0"
      41. __p_8__ | val | avg | 20 | 0 | "val_avg_piv_20_piv2_0"
      42. __p_13__ | val | avg | 30 | 100 | "val_avg_piv_30_piv2_100"
      43. __p_17__ | val2 | avg | | 100 | "val2_avg_piv_null_piv2_100"
      44. __p_22__ | val2 | avg | 10 | 200 | "val2_avg_piv_10_piv2_200"
      45. __p_26__ | val2 | avg | 20 | 200 | "val2_avg_piv_20_piv2_200"
      46. __p_31__ | val2 | avg | 30 | 300 | "val2_avg_piv_30_piv2_300"
      47. __p_35__ | val2 | sum | | 300 | "val2_sum_piv_null_piv2_300"
      48. __p_39__ | val2 | sum | 10 | 300 | "val2_sum_piv_10_piv2_300"
      49. __p_40__ | val2 | sum | 20 | 0 | "val2_sum_piv_20_piv2_0"
      50. __p_44__ | val2 | sum | 30 | 0 | "val2_sum_piv_30_piv2_0"
      51. (48 rows)
      1. SELECT * FROM pivout ORDER BY id,id2;
      1. -[ RECORD 1 ]--
      2. id | 0
      3. id2 | 0
      4. __p_0__ | 111
      5. __p_1__ | 111
      6. __p_2__ | 111
      7. __p_3__ | 111
      8. __p_4__ | 1
      9. __p_5__ | 111
      10. __p_6__ | 111
      11. __p_7__ | 111
      12. __p_8__ | 111
      13. __p_9__ | 111
      14. __p_10__ | 111
      15. __p_11__ | 111
      16. __p_12__ | 111
      17. __p_13__ | 111
      18. __p_14__ | 111
      19. __p_15__ | 111
      20. __p_16__ | 111
      21. __p_17__ | 111
      22. __p_18__ | 111
      23. __p_19__ | 111
      24. __p_20__ | 11
      25. __p_21__ | 111
      26. __p_22__ | 111
      27. __p_23__ | 111
      28. __p_24__ | 111
      29. __p_25__ | 111
      30. __p_26__ | 111
      31. __p_27__ | 111
      32. __p_28__ | 111
      33. __p_29__ | 111
      34. __p_30__ | 111
      35. __p_31__ | 111
      36. __p_32__ | 111
      37. __p_33__ | 111
      38. __p_34__ | 111
      39. __p_35__ | 111
      40. __p_36__ | 11
      41. __p_37__ | 111
      42. __p_38__ | 111
      43. __p_39__ | 111
      44. __p_40__ | 111
      45. __p_41__ | 111
      46. __p_42__ | 111
      47. __p_43__ | 111
      48. __p_44__ | 111
      49. __p_45__ | 111
      50. __p_46__ | 111
      51. __p_47__ | 111
      52. -[ RECORD 2 ]--
      53. id | 0
      54. id2 | 1
      55. __p_0__ | 111
      56. __p_1__ | 111
      57. __p_2__ | 111
      58. __p_3__ | 111
      59. __p_4__ | 111
      60. __p_5__ | 2
      61. __p_6__ | 111
      62. __p_7__ | 111
      63. __p_8__ | 111
      64. __p_9__ | 3
      65. __p_10__ | 111
      66. __p_11__ | 111
      67. __p_12__ | 111
      68. __p_13__ | 111
      69. __p_14__ | 111
      70. __p_15__ | 111
      71. __p_16__ | 111
      72. __p_17__ | 111
      73. __p_18__ | 111
      74. __p_19__ | 111
      75. __p_20__ | 111
      76. __p_21__ | 12
      77. __p_22__ | 111
      78. __p_23__ | 111
      79. __p_24__ | 111
      80. __p_25__ | 13
      81. __p_26__ | 111
      82. __p_27__ | 111
      83. __p_28__ | 111
      84. __p_29__ | 111
      85. __p_30__ | 111
      86. __p_31__ | 111
      87. __p_32__ | 111
      88. __p_33__ | 111
      89. __p_34__ | 111
      90. __p_35__ | 111
      91. __p_36__ | 111
      92. __p_37__ | 12
      93. __p_38__ | 111
      94. __p_39__ | 111
      95. __p_40__ | 111
      96. __p_41__ | 13
      97. __p_42__ | 111
      98. __p_43__ | 111
      99. __p_44__ | 111
      100. __p_45__ | 111
      101. __p_46__ | 111
      102. __p_47__ | 111
      103. ...

      参考

      [1]PostgreSQL 8.2 Aggregate Functions [2]PostgreSQL 8.2 CREATE AGGREGATE [3]PostgreSQL 8.2 User-Defined Aggregates