【问题标题】:Using a variable period in an interval in Postgres在 Postgres 的间隔中使用可变周期
【发布时间】:2011-12-09 10:42:39
【问题描述】:

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

这是我所拥有的:

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

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

【问题讨论】:

    标签: postgresql variables intervals period


    【解决方案1】:

    使用这一行:

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

    并注意MONTH 之前的空格。 基本上:你用4 MONTH 构造一个字符串,然后用::type 将它转换成适当的间隔。

    编辑:我找到了另一种解决方案:您可以像这样使用interval 进行计算:

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

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

    【讨论】:

    • 或者:endDate - '1 mon'::interval * $3(更少的转换和连接)
    • @A.H.酷:) 记得@reply in comments 否则我可能会错过你的答案。
    • 与区间相乘是一个很好的解!
    【解决方案2】:

    此代码与您的情况没有直接关系,但它确实说明了如何在 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;
    

    【讨论】:

      【解决方案3】:

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

      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 中以整数形式传递 - 因此不太可能出现意外后果。

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-25
          • 2019-07-18
          • 1970-01-01
          • 2014-08-27
          • 2013-10-28
          相关资源
          最近更新 更多