Com*_*mic 6 postgresql aggregate pivot aggregate-filter
在 PostgreSQL 9.5 中,我有一个名为的表reports
:
CREATE TABLE public.reports (
id BIGSERIAL PRIMARY KEY,
id_station character(11) NOT NULL,
date date NOT NULL,
element character(4) NOT NULL,
value smallint NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
对于每个站(id_station
列)和每一天(date
列),我可能有多个值类型(元素列) : TMIN
, TMAX
, TAVG
(有时这些值不存在:对于给定的一天,我可能只有 aTMIN
和 a TMAX
)。
这是一个(假)样本:
22;"FR069029001";"1925-01-01";"TMAX";130
23;"FR069029001";"1925-01-01";"TMIN";-25
24;"FR069029001";"1925-01-01";"TAVG";0
Run Code Online (Sandbox Code Playgroud)
我想使用此表将每个站点和每天的这些值合并在一行中:
CREATE TABLE public.reports_con (
id SERIAL PRIMARY KEY,
id_station character(11) NOT NULL,
date date NOT NULL,
tmin smallint,
tmax smallint,
tavg smallint
);
Run Code Online (Sandbox Code Playgroud)
我想达到这个结果:
454;"FR069029001";"1925-01-01";-25;130;0
Run Code Online (Sandbox Code Playgroud)
如何在PostgreSQL中以这种方式整合数据?与CREATE TABLE AS
?
我知道它必须是这样的递归查询(人类语言):
For each day:
For each station:
Find values for TMIN, TMAX, TAVG
Insert the results in reports_con in a single row with day and station
Run Code Online (Sandbox Code Playgroud)
我开始学习 SQL 并希望在 PostgreSQL 中实现这一点(而不是使用 Python 或编程语言)。你能帮我么?
由于目标表显然存在,CREATE TABLE AS
因此与解决方案无关。而且您当然也不需要递归查询。
对于仅三列,您可以使用条件聚合:
INSERT INTO reports_con (id_station, date, tmin, tmax, tavg)
SELECT id_station, date
, min(value) FILTER (WHERE element = 'TMIN') AS tmin
, min(value) FILTER (WHERE element = 'TMAX') AS tmax
, min(value) FILTER (WHERE element = 'TAVG') AS tavg
FROM reports
GROUP BY id_station, date
ORDER BY id_station, date;
Run Code Online (Sandbox Code Playgroud)
聚合FILTER
子句需要 Postgres 9.4。旧版本的详细信息和替代方案:
对于更多列或大量行(并且您需要更好的性能),请考虑实际crosstab()
查询。特别困难的是您的密钥由两列组成,但您需要一列用于crosstab()
. 在这些相关答案中生成类似的代理键row_number()
:
归档时间: |
|
查看次数: |
13662 次 |
最近记录: |