war*_*ect 5 postgresql aggregate greatest-n-per-group postgresql-9.4
我有一个查询,其中按站点和月份返回平均值。我想知道的是按站点划分的月平均值的最小值和最大值以及(困难的部分)每个发生的月份。
这是一个例子:
CREATE TABLE events (
esite integer NOT NULL,
edate timestamp with time zone NOT NULL,
evalue integer NOT NULL
);
INSERT INTO events Values
(1, '2016-01-03', 11),
(2, '2016-01-05', 90),
(1, '2016-01-08', 7),
(2, '2016-01-10', 40),
(1, '2016-01-15', 12),
(1, '2016-01-18', 66),
(2, '2016-01-22', 54),
(2, '2016-02-03', 70),
(2, '2016-02-05', 56),
(1, '2016-02-08', 61),
(2, '2016-02-10', 23),
(1, '2016-02-15', 30),
(1, '2016-02-18', 15),
(1, '2016-02-22', 41);
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个查询,该查询返回(按站点)最小和最大月平均值evalue
以及最小和最大值发生的月份。我可以通过使用下面的查询得到这个:
select esite, date_trunc('month', edate) as emonth, round(avg(evalue),2) as evalue_avg from events
Group by esite, emonth
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
esite | emonth | evalue_avg
2 | January, 01 2016 00:00:00 | 61.33
1 | January, 01 2016 00:00:00 | 24
1 | February, 01 2016 00:00:00 | 36.75
2 | February, 01 2016 00:00:00 | 49.67
Run Code Online (Sandbox Code Playgroud)
现在,对于我遇到困难的部分,我需要生成以下结果 - 基本上是最小值、最大值以及每个站点发生的日期(月份)。
期望的输出:
-- (one row per site)
esite | avg_min | eval_avg_min_date | avg_max | eval_avg_max
1 | 24.00 | January, 01 2016 00:00:00 | 36.75 | February, 01 2016 00:00:00
2 | 49.67 |February, 01 2016 00:00:00 | 61.33 | January, 01 2016 00:00:00
Run Code Online (Sandbox Code Playgroud)
我四处搜索并看到了一些使用窗口和横向连接的示例,但我还没有成功地让它们工作。这可能是一个枢纽,但由于我没有固定数量的站点,这对于 PostgreSQL 来说往往很困难。
我猜是否有人有一个简单的方法使用 Postgres 9.4+ 来做到这一点。
我建议你做这样的事情 - 并且不要走每月排行的道路。
当您有 5 (10...15... x) 年的数据时会发生什么?
恕我直言,这是优越的。您始终可以使用CROSSTAB
表函数,但我建议不要使用它。
SELECT
esite,
MIN(evalue),
MAX(evalue),
AVG(evalue)::INT,
EXTRACT(MONTH FROM edate) AS emonth,
CASE
WHEN EXTRACT(MONTH FROM edate) = 1 THEN 'January'
WHEN EXTRACT(MONTH FROM edate) = 2 THEN 'February'
-- <... fill in rest of months here ...>
END AS litMonth
FROM events
GROUP BY esite, emonth, litMonth
ORDER BY esite, emonth -- , min, max, avg;
Run Code Online (Sandbox Code Playgroud)
这给出了结果:
esite; min; max; avg; emonth; litmonth
----------------------------------------------------
1; 7; 66; 24; 1; January
1; 15; 61; 37; 2; February
2; 40; 90; 61; 1; January
2; 23; 70; 50; 2; February
Run Code Online (Sandbox Code Playgroud)
请注意,我将CAST
AVG 作为INTEGER
- 您当然可以ROUND
将其关闭到您喜欢的任何内容。您可以EXTRACT(YEAR FROM edate) AS eyear,
在后面添加EXTRACT(MONTH...
以获得更清晰和更优雅的结果。
归档时间: |
|
查看次数: |
1585 次 |
最近记录: |