比较当月的一天和上个月的同一天PostgreSQL
Posted
技术标签:
【中文标题】比较当月的一天和上个月的同一天PostgreSQL【英文标题】:Compare day in current month to same day previous month PostgreSQL 【发布时间】:2018-04-23 17:14:52 【问题描述】:我正在尝试使用 PostgreSQL 将当前月份的数据值与前几个月的数据值进行比较。因此,如果今天是 2018 年 4 月 23 日,我想要 2018 年 3 月 23 日的数据。
我已经尝试过current_date - interval '1 month'
,但它在 31 天的几个月里都有问题。
我的表格结构很简单
日期,值
【问题讨论】:
那么您预计上个月的 31 号日期是多少? 第 31 天为空 【参考方案1】:检查这个示例查询:
WITH dates AS (SELECT date::date FROM generate_series('2018-01-01'::date, '2018-12-31'::date, INTERVAL '1 day') AS date)
SELECT
start_dates.date AS start_date,
end_dates.date AS end_date
FROM
dates AS start_dates
RIGHT JOIN dates AS end_dates
ON ( start_dates.date + interval '1 month' = end_dates.date AND
end_dates.date - interval '1 month' = start_dates.date);
它将输出所有end_dates
和对应的start_dates
。对应的日期由interval '1 month'
定义并以两种方式检查:
start_dates.date + interval '1 month' = end_dates.date AND
end_dates.date - interval '1 month' = start_dates.date
输出如下:
....
2018-02-26 2018-03-26
2018-02-27 2018-03-27
2018-02-28 2018-03-28
2018-03-29
2018-03-30
2018-03-31
2018-03-01 2018-04-01
2018-03-02 2018-04-02
2018-03-03 2018-04-03
2018-03-04 2018-04-04
....
请注意,没有相应日期的日子会有“间隔”。
回到您的表,将表与自身连接(给出别名)并使用给定的连接条件,因此查询将如下所示:
SELECT
start_dates.value - end_dates.value AS change,
start_dates.date AS start_date,
end_dates.date AS end_date
FROM
_your_table_name_ AS start_dates
RIGHT JOIN _your_table_name_ AS end_dates
ON ( start_dates.date + interval '1 month' = end_dates.date AND
end_dates.date - interval '1 month' = start_dates.date);
【讨论】:
谢谢!我应该提到我正在使用 Redshift,所以 generate_series 不起作用。我尝试了一个替代方案:WITH dates AS (select (current_date::date - generate_series)::date as date from generate_series(1,1000,1)) SELECT start_dates.date AS start_date, end_dates.date AS end_date FROM dates AS start_dates RIGHT JOIN dates AS end_dates ON ( start_dates.date + interval '1 month' = end_dates.date AND end_dates.date - interval '1 month' = start_dates.date )
但鉴于 Redshift 的限制,它不能加入任何其他表
这只是一个例子。删除WITH
子句并将dates
替换为您的真实表名(table_name AS start_dates RIGHT JOIN table_name AS end_dates)。一般来说:将表与自身连接(给出别名)并使用给定的连接条件。【参考方案2】:
给定以下表结构:
create table t (
d date,
v int
);
在填充了一些日期和值之后,有一种方法可以使用简单的计算和LAG 函数来查找上个月的值,而无需借助连接。我不确定它从性能角度如何比较,因此请在选择要使用的解决方案之前运行您自己的测试。
select
*,
lag(v, day_of_month) over (order by d) as v_end_of_last_month,
lag(v, last_day_of_previous_month + day_of_month - cast(extract(day from d - interval '1 month') as int)) over (order by d) as v_same_day_last_month
from (
select
*,
lag(day_of_month, day_of_month) over (order by d) as last_day_of_previous_month
from (
select
*,
cast(extract(day from d) as int) as day_of_month
from
t
) t_dom
) t_dom_ldopm;
您可能会注意到,在 3 月 29 日至 31 日之间,将与 2 月 28 日进行比较,因为这些特定日期在 2 月不存在同一天。相同的逻辑适用于其他天数不同的月份。
【讨论】:
以上是关于比较当月的一天和上个月的同一天PostgreSQL的主要内容,如果未能解决你的问题,请参考以下文章