Mar*_*arc 2 postgresql crosstab postgresql-9.4
我有一张“瘦高”事实表:
CREATE TABLE facts(
eff_date timestamp NOT NULL,
update_date timestamp NOT NULL,
symbol_id int4 NOT NULL,
data_type_id int4 NOT NULL,
source_id char(3) NOT NULL,
fact decimal
/* Keys */
CONSTRAINT fact_pk
PRIMARY KEY (source_id, symbol_id, data_type_id, eff_date),
)
Run Code Online (Sandbox Code Playgroud)
我想“透视”这个报告,所以标题看起来像这样:
eff_date, symbol_id, source_id, datatypeValue1, ... DatatypeValueN
Run Code Online (Sandbox Code Playgroud)
即,对于 eff_date、symbol_id 和 source_id 的每个唯一组合,我想要一行。
但是,postgresql crosstab() 函数只允许键列。
有任何想法吗?
crosstab() 期望来自其输入查询(第一个参数)的以下列,按此顺序:
row_nameextra列category(匹配第二个交叉表参数中的值)value你没有row_name. 添加row_name具有窗口函数的代理dense_rank()。
你的问题留下了解释的空间。让我们添加示例行进行演示:
INSERT INTO facts (eff_date, update_date, symbol_id, data_type_id, source_id)
VALUES
(now(), now(), 1, 5, 'foo')
, (now(), now(), 1, 6, 'foo')
, (now(), now(), 1, 7, 'foo')
, (now(), now(), 1, 6, 'bar')
, (now(), now(), 1, 7, 'bar')
, (now(), now(), 1, 23, 'bar')
, (now(), now(), 1, 5, 'baz')
, (now(), now(), 1, 23, 'baz'); -- only two rows for 'baz'
Run Code Online (Sandbox Code Playgroud)
要列出前N值的data_type_id(最小的,如果有更多的),为每个不同的(source_id, symbol_id, eff_date)。
为此,您还需要一个合成category,可以与row_number(). 生成输入的基本查询crosstab():
SELECT dense_rank() OVER (ORDER BY eff_date, symbol_id, source_id)::int AS row_name
, eff_date, symbol_id, source_id -- extra columns
, row_number() OVER (PARTITION BY eff_date, symbol_id, source_id
ORDER BY data_type_id)::int AS category
, data_type_id AS value
FROM facts
ORDER BY row_name, category;
Run Code Online (Sandbox Code Playgroud)
交叉表查询:
SELECT *
FROM crosstab(
'SELECT dense_rank() OVER (ORDER BY eff_date, symbol_id, source_id)::int AS row_name
, eff_date, symbol_id, source_id -- extra columns
, row_number() OVER (PARTITION BY eff_date, symbol_id, source_id
ORDER BY data_type_id)::int AS category
, data_type_id AS value
FROM facts
ORDER BY row_name, category'
, 'VALUES (1), (2), (3)'
) AS (row_name int, eff_date timestamp, symbol_id int, source_id char(3)
, datatype_1 int, datatype_2 int, datatype_3 int);
Run Code Online (Sandbox Code Playgroud)
结果:
行名称 | 生效日期 | 符号_id | source_id | 数据类型_1 | 数据类型_2 | 数据类型_3
-------: | :--------------| --------: | :-------- | ---------: | ---------: | ---------:
1 | 2017-04-10 ... | 1 | 酒吧| 6 | 7 | 23
2 | 2017-04-10 ... | 1 | 巴兹| 5 | 23 | 空值
3 | 2017-04-10 ... | 1 | 富| 5 | 6 | 7
您想将 的实际值附加data_type_id到列名datatypeValue1, ... DatatypeValueN。其中一个或多个:
SELECT DISTINCT data_type_id FROM facts ORDER BY 1;
Run Code Online (Sandbox Code Playgroud)
5, 6, 7, 23在示例中。那么实际显示值可以只是boolean(或冗余值?)。基本查询:
SELECT dense_rank() OVER (ORDER BY eff_date, symbol_id, source_id)::int AS row_name
, eff_date, symbol_id, source_id -- extra columns
, data_type_id AS category
, TRUE AS value
FROM facts
ORDER BY row_name, category;
Run Code Online (Sandbox Code Playgroud)
交叉表查询:
SELECT *
FROM crosstab(
'SELECT dense_rank() OVER (ORDER BY eff_date, symbol_id, source_id)::int AS row_name
, eff_date, symbol_id, source_id -- extra columns
, data_type_id AS category
, TRUE AS value
FROM facts
ORDER BY row_name, category'
, 'VALUES (5), (6), (7), (23)' -- actual values
) AS (row_name int, eff_date timestamp, symbol_id int, source_id char(3)
, datatype_5 bool, datatype_6 bool, datatype_7 bool, datatype_23 bool);
Run Code Online (Sandbox Code Playgroud)
结果:
生效日期 | 符号_id | source_id | 数据类型_5 | 数据类型_6 | 数据类型_7 | 数据类型_23 :--------------| --------: | :-------- | :--------- | :--------- | :--------- | :---------- 2017-04-10 ... | 1 | 酒吧| 空 | 吨| 吨| 吨 2017-04-10 ... | 1 | 巴兹| 吨| 空 | 空 | 吨 2017-04-10 ... | 1 | 富| 吨| 吨| 吨| 空值
dbfiddle在这里
有关的:
| 归档时间: |
|
| 查看次数: |
6703 次 |
| 最近记录: |