72

我有一个维护每月历史数据的关系。此数据在每个月的最后一天添加到表中。然后可以调用我正在编写的服务,指定要检索历史数据的月份和月份。我通过创建 startDate 和 endDate 变量,然后返回两者之间的数据来做到这一点。我遇到的问题是 startDate 是 endDate 之前的可变月数,我无法弄清楚如何在间隔中使用可变期间。

这是我所拥有的:

    DECLARE
      endDate   TIMESTAMP := (DATE_TRUNC('MONTH',$2) + INTERVAL '1 MONTH') - INTERVAL '1 DAY';
      startDate TIMESTAMP := endDate - INTERVAL $3 'MONTH';

我知道 startDate 的行不正确。这是如何正确完成的?

4

4 回答 4

126

使用这一行:

startDate TIMESTAMP := endDate - ($3 || ' MONTH')::INTERVAL;

并注意前面的空格MONTH。基本上:您使用 like 构造一个字符串4 MONTH并将其::type转换为适当的间隔。

编辑:我找到了另一个解决方案:您可以interval这样计算:

startDate TIMESTAMP := endDate - $3 * INTERVAL '1 MONTH';

这对我来说看起来更好一些。

于 2011-10-17T18:34:41.527 回答
9

此代码与您的情况没有直接关系,但它确实说明了如何在 INTERVAL 算术中使用变量。我的表的名称是“日历”。

CREATE OR REPLACE FUNCTION test_param(num_months integer)
  RETURNS SETOF calendar AS
$BODY$

    select * from calendar
    where cal_date <= '2008-12-31 00:00:00'
    and cal_date > date '2008-12-31' - ($1 || ' month')::interval;

$BODY$
  LANGUAGE sql VOLATILE
  COST 100
  ROWS 1000;
于 2011-10-17T18:35:07.227 回答
0

我发现将可变时间段传递给 Postgres 的最易读的方法类似于 AH 的答案:乘以一个整数。但这可以在没有演员表的情况下完成。

Python 示例(使用sqlalchemypandas):

import pandas as pd
import sqlalchemy as sa

connection = sa.create_engine(connection_string)

df = pd.read_sql(
   sa.text('''
       select * from events
       where
       event_date between now() - (interval '1 day' * :ndays) and now()
       limit 100;
'''),
   connection,
   params={'ndays': 100}
)

天数 ( ndays ) 在 Python 中作为整数传递 - 因此不太可能出现意外后果。

于 2021-02-25T17:45:00.930 回答
0

我的方法是这样的。它让我可以选择设置特定日期或相对范围。

create or replace function search_data(_time_from timestamptz default null, _last_interval text default null)
    returns setof journal
    language plpgsql as
$$
begin
    return query
        select *
        from journal
        where created >= case
                             when _time_from is not null
                                 then _time_from
                             else now() - _last_interval::interval end;
end;
$$;
于 2021-09-03T22:07:48.467 回答