postgreSQL选择昨天的值,月平均值

postgreSQL选择昨天的值,月平均值,sql,postgresql,Sql,Postgresql,我有一个PostgreSQL表: create table UV( f_date int, uv bigint ) 数据: 那么,如何使用sql生成这样的表: f_date | uv_today | uv_yesterday | uv_month_avg ---------+------------+--------------+-------------- 20150103 | 620964 |(uv of 20150102)| average uv from 201412

我有一个PostgreSQL表:

create table UV(
f_date int,
uv bigint
)
数据:

那么,如何使用sql生成这样的表:

f_date   |   uv_today | uv_yesterday |  uv_month_avg
---------+------------+--------------+--------------
20150103 | 620964     |(uv of 20150102)| average uv from 20141204 to 20150103
20150104 | 595367     |  620964        |

我会选择选择列表中的子选择:

select f_date,
       uv as uv_today,
       (select uv from uv as u2
        where u2.f_date = uv.f_fdate - 1) as uv_yesterday,
       (select avg(uv) from uv as u2
        where u2.f_date between uv.f_fdate - 30 and uv.f_fdate) as uv_month_avg
from uv
请注意,我不想正确计算负1个月,因为我不知道在postgresql中如何计算,只需要-30天。

首先:不要将日期存储为整数!如果您想要日期,请使用
date
!尤其不要将日期存储为整数,位置值用于表示年、月和日。认真地在继续实际使用该模式之前,需要先修复该模式。将历元值存储为朱利安日期,或使用本机数据类型
日期
时间戳
间隔
进行正确的日期/时间工作

第一部分是一个窗口函数的简单应用;只需
延迟(uv,1)超过(按f_日期订购)

第二种方法有点棘手,但是一旦你修复了你的模式,它就不会太糟糕了。假设您想要一个日历月,您可以在(按日期划分(“月”,f_日期))上使用
avg(uv)
。如果你想要30天的间隔,那是另一回事

比如:

create table UV(
f_date date,
uv bigint
);

insert into UV (f_date, uv)
VALUES ('20150103', '620964'),
       ('20150104', '595367');

SELECT
  f_date,
  uv,
  lag(uv, 1) OVER (ORDER BY f_date),
  avg(uv) OVER (PARTITION BY date_trunc('month', f_date))
FROM UV;

如图所示:

-interval'1'month
@CraigRinger,即使将日期存储为int?我只是在发表评论后才注意到。在这种情况下,正确的做法是不将日期存储为int,因为这太可怕了。或者强制转换它或其他什么。稍微少于绝对最小的样本数据是有用的,尽管这肯定比没有好。为什么要使用bigint作为日期?您应该将日期存储在
date
列中。我将尝试修复我的模式。
create table UV(
f_date date,
uv bigint
);

insert into UV (f_date, uv)
VALUES ('20150103', '620964'),
       ('20150104', '595367');

SELECT
  f_date,
  uv,
  lag(uv, 1) OVER (ORDER BY f_date),
  avg(uv) OVER (PARTITION BY date_trunc('month', f_date))
FROM UV;