比较当前月份的当天和上个月的同一天PostgreSQL

时间:2018-04-23 17:14:53

标签: postgresql date amazon-redshift

我正在尝试使用PostgreSQL将当前月份数据的值与前几个月进行比较。因此,如果今天是4/23/2018,我想要3/23/2018的数据。

我已经尝试了current_date - interval '1 month'但是这个问题持续了31个月。

我的表格结构简单

  

日期,价值

2 个答案:

答案 0 :(得分:0)

检查此示例查询:

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);

答案 1 :(得分:0)

给出以下表结构:

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月不存在同一天。相同的逻辑适用于其他天数不同的月份。