我在Postgres工作时有这样一个表:
mon yyyy weather
Apr 2014 78.45
Apr 2015 77.32
May 2014 79.56
May 2015 78.43
我希望能够查询一些结果,按照" mon"排序,其中weather
列值按年逐月划分。
换句话说,我想查询2015年4月除以2014年4月的天气。
但是,我想以这样的方式编写查询:我不必指定月份或年份,查询会根据以下内容自动划分weather
值:2014年4月/ 2014年4月,然后是2014年5月/ 2014年5月,无需每月和每年关键,这很费力。
我有以下代码,但这会扩展不是我想要的列:
select (select "Weather" from yoy
where mon = 'Apr' and yyyy = '2015'
)/(select "American" from yoy
where mon = 'Apr' and yyyy = '2014'
) as "weather_apr",
(select "Weather" from yoy
where mon = 'May' and yyyy = '2015'
)/(select "Weather" from yoy
where mon = 'May' and yyyy = '2014'
) as "weather_may",
from yoy;
答案 0 :(得分:1)
在我看来,这是利用分析window function的正确方案。这里没有连接的魔力:
SELECT yyyy,
weather,
mon,
lead( weather ) over (partition by mon order by mon, yyyy desc),
weather / lead( weather ) over (partition by mon order by mon, yyyy desc)
FROM joy
答案 1 :(得分:0)
我认为你需要一个自我加入,如下例所示:
SELECT j1."yyyy" As year,
j2."yyyy" As next_year,
j1."mon",
j1."weather",
j2."weather" As "weather from next year",
j1."weather"::float / j2."weather" As divide
FROM joy j1
JOIN joy j2
ON j1."yyyy" = j2."yyyy" - 1 AND j1."mon" = j2."mon"
答案 2 :(得分:0)
您可以使用表yoy
的自联接。请参阅此查询,该查询将当前年与上一个加入:
select *
from yoy a
join yoy b on a.yyyy::int = b.yyyy::int+ 1 and a.mon = b.mon
mon | yyyy | weather | mon | yyyy | weather
-----+------+---------+-----+------+---------
Apr | 2015 | 77.32 | Apr | 2014 | 78.45
May | 2015 | 78.43 | May | 2014 | 79.56
(2 rows)
现在您可以轻松进行计算:
select a.mon, a.weather/ b.weather as weather
from yoy a
join yoy b on a.yyyy::int = b.yyyy::int+ 1 and a.mon = b.mon
mon | weather
-----+------------------------
Apr | 0.98559592096876991714
May | 0.98579688285570638512
(2 rows)
答案 3 :(得分:0)
我发现条件聚合对于这种类型的查询非常有用:
select mon,
max(case when yyyy = 2014 then weather end) as weather_2014,
max(case when yyyy = 2015 then weather end) as weather_2015,
(max(case when yyyy = 2015 then weather end) /
max(case when yyyy = 2014 then weather end)
) as ratio
from yoy
group by mon
这假设您希望每月减少一行。要获取上一个值,只需使用lag()
:
select yoy.*,
lag(weather) over (partition by month order by year) as prev_weather
from yoy;