3 回答
TA贡献1809条经验 获得超8个赞
CREATE EXTENSION tablefunc;
对问题的回答
SELECT * FROM crosstab( 'SELECT bar, 1 AS cat, feh FROM tbl_org ORDER BY bar, feh') AS ct (bar text, val1 int, val2 int, val3 int); -- more columns?
cat
crosstab()NULL
crosstab()row_number()crosstab()
SELECT * FROM crosstab(
$$
SELECT bar, val, feh FROM (
SELECT *, 'val' || row_number() OVER (PARTITION BY bar ORDER BY feh) AS val FROM tbl_org ) x ORDER BY 1, 2
$$
, $$VALUES ('val1'), ('val2'), ('val3')$$ -- more columns?) AS ct (bar text, val1 int, val2 int, val3 int); -- more columns?基本要素:crosstab()
高级:
适当的测试装置
CREATE TEMP TABLE tbl_org (id int, feh int, bar text);INSERT INTO tbl_org (id, feh, bar) VALUES (1, 10, 'A') , (2, 20, 'A') , (3, 3, 'B') , (4, 4, 'B') , (5, 5, 'C') , (6, 6, 'D') , (7, 7, 'D') , (8, 8, 'D');
动态交叉表?
CREATE TEMP TABLE tbl (row_name text, attrib text, val int);INSERT INTO tbl (row_name, attrib, val) VALUES
('A', 'val1', 10)
, ('A', 'val2', 20)
, ('B', 'val1', 3)
, ('B', 'val2', 4)
, ('C', 'val1', 5)
, ('D', 'val3', 8)
, ('D', 'val1', 6)
, ('D', 'val2', 7);SELECT * FROM crosstab('SELECT row_name, attrib, val FROM tbl ORDER BY 1,2')AS ct (row_name text, val1 int, val2 int, val3 int);row_name | val1 | val2 | val3----------+------+------+------ A | 10 | 20 | B | 3 | 4 | C | 5 | | D | 6 | 7 | 8
内建特征 tablefunc模块
crosstab()C
crosstabN()
crosstab1() - crosstab4()textinteger
SELECT * FROM crosstab4('SELECT row_name, attrib, val::text -- cast!
FROM tbl ORDER BY 1,2')row_name | category_1 | category_2 | category_3 | category_4----------+------------+------------+------------+------------ A | 10 | 20 | | B | 3 | 4 | | C | 5 | | | D | 6 | 7 | 8 |
习俗 crosstab()功能
CREATE TYPE tablefunc_crosstab_int_5 AS ( row_name text, val1 int, val2 int, val3 int, val4 int, val5 int);
CREATE OR REPLACE FUNCTION crosstab_int_5(text) RETURNS SETOF tablefunc_crosstab_int_5AS '$libdir/tablefunc', 'crosstab' LANGUAGE c STABLE STRICT;
SELECT * FROM crosstab_int_5('SELECT row_name, attrib, val -- no cast!
FROM tbl ORDER BY 1,2');row_name | val1 | val2 | val3 | val4 | val5----------+------+------+------+------+------ A | 10 | 20 | | | B | 3 | 4 | | | C | 5 | | | | D | 6 | 7 | 8 | |
一多态的,动态的
tablefunc
CREATE OR REPLACE FUNCTION crosstab_n(_qry text, _rowtype anyelement)
RETURNS SETOF anyelement AS$func$BEGIN
RETURN QUERY EXECUTE
(SELECT format('SELECT * FROM crosstab(%L) t(%s)'
, _qry , string_agg(quote_ident(attname) || ' ' || atttypid::regtype
, ', ' ORDER BY attnum))
FROM pg_attribute WHERE attrelid = pg_typeof(_rowtype)::text::regclass AND attnum > 0
AND NOT attisdropped);END$func$ LANGUAGE plpgsql;CREATE OR REPLACE FUNCTION crosstab_n(_qry text, _cat_qry text, _rowtype anyelement)
RETURNS SETOF anyelement AS$func$BEGIN
RETURN QUERY EXECUTE
(SELECT format('SELECT * FROM crosstab(%L, %L) t(%s)'
, _qry, _cat_qry , string_agg(quote_ident(attname) || ' ' || atttypid::regtype
, ', ' ORDER BY attnum))
FROM pg_attribute WHERE attrelid = pg_typeof(_rowtype)::text::regclass AND attnum > 0
AND NOT attisdropped);END$func$ LANGUAGE plpgsql;pg_typeof(_rowtype)::text::regclasspg_attributeregtypetexttextregclass.
创建组合类型一次:
CREATE TYPE tablefunc_crosstab_int_3 AS ( row_name text, val1 int, val2 int, val3 int);CREATE TYPE tablefunc_crosstab_int_4 AS ( row_name text, val1 int, val2 int, val3 int, val4 int);...
CREATE TEMP TABLE temp_xtype7 AS ( row_name text, x1 int, x2 int, x3 int, x4 int, x5 int, x6 int, x7 int);
打电话
SELECT * FROM crosstab_n( 'SELECT row_name, attrib, val FROM tbl ORDER BY 1,2' , NULL::tablefunc_crosstab_int_3);
SELECT * FROM crosstab_n(
'SELECT row_name, attrib, val FROM tbl ORDER BY 1'
, $$VALUES ('val1'), ('val2'), ('val3')$$
, NULL::tablefunc_crosstab_int_3);crosstabN()tablefunc
SELECT max(count(*)) OVER () FROM tbl -- returns 3GROUP BY row_name LIMIT 1;
jsonhstore
免责声明:
要求提出原始问题:
SELECT * FROM crosstab_n('SELECT bar, 1, feh FROM tbl_org ORDER BY 1,2'
, NULL::tablefunc_crosstab_int_3);TA贡献1856条经验 获得超5个赞
json_object_agg
select
row_name as bar,
json_object_agg(attrib, val order by attrib) as datafrom
tbl right join
(
(select distinct row_name from tbl) a cross join
(select distinct attrib from tbl) b ) c using (row_name, attrib)group by row_nameorder by row_name;
bar | data
-----+----------------------------------------------
a | { "val1" : 10, "val2" : 20, "val3" : null }
b | { "val1" : 3, "val2" : 4, "val3" : null }
c | { "val1" : 5, "val2" : null, "val3" : null }
d | { "val1" : 6, "val2" : 7, "val3" : 8 }添加回答
举报
