PostgreSQL 检查前一条记录的元素

标签 postgresql datetime plpgsql window-functions

我需要检查上一条记录的元素,以确保我查询的日期不在结束日期和开始日期前 7 天之间的特定范围内。我有以下代码:

create or replace function eight (date) returns text as $$
declare
  r record;
  checkDate alias for $1;
begin
    for r in
    select * from periods
    order by startDate
  loop
    if (checkDate between r.startDate and r.endDate) then
      return q3(r.id);
    elsif (checkDate between (r.startDate - interval '7 days') and r.startDate) then
      return q3(r.id);
    elsif (checkDate between (lag(r.endDate) over (order by r.startDate)) and (r.startDate - interval '8 days')) then
      return q3(r.id);
    end if;
  end loop;
  return null;
end;
$$ language plpgsql;

所以基本上,我需要检查以下内容:

  • 如果查询日期介于开始日期和结束日期之间

  • 如果查询日期为起始日期前7天

  • 如果查询日期介于结束日期和开始日期之间 并返回与该日期关联的 ID。

我的函数在大多数情况下似乎工作正常,但在某些情况下似乎给我 0 个结果(当应该始终有 1 个结果时)我的函数中是否缺少某些内容?我对最后一个 if 语句持怀疑态度。也就是说,尝试从以前的记录结束日期检查到当前记录的开始日期(有 7 天的间隙)

编辑:没有日期重叠。

最佳答案

编辑:删除了有关 RETURN NEXT 的部分 - 我误读了那里的问题。
不按照你的方式工作。一个window function不能这样称呼。您的记录变量r 就像FOR 循环中的内置光标。只有结果的当前行在循环内可见。您必须集成 window function lag()将其放入初始的SELECT中。

但是由于您无论如何都按照匹配的顺序循环遍历行,因此您可以采用另一种方式。

考虑这个很大程度上重写的示例。返回第一个违规行:

CREATE OR REPLACE FUNCTION q8(_day date)
  RETURNS text AS
$BODY$
DECLARE
    r            record;
    last_enddate date;

BEGIN
FOR r IN
    SELECT *
       -- ,lag(r.endDate) OVER (ORDER BY startDate) AS last_enddate
       -- commented, because I supply an alternative solution
    FROM   periods
    ORDER  BY startDate
LOOP
    IF _day BETWEEN r.startDate AND r.endDate THEN
        RETURN 'Violates condition 1';  -- I return differing results
    ELSIF _day BETWEEN (r.startDate - 7) AND r.startDate THEN
        RETURN 'Violates condition 2';
    ELSIF _day BETWEEN last_enddate AND (r.startDate) THEN 
                                      -- removed "- 7 ", that is covered above
        RETURN 'Violates condition 3';
    END IF;

    last_enddate := r.enddate; -- remember for next iteration
END LOOP;

RETURN NULL;

END;
$BODY$ LANGUAGE plpgsql;

更多提示

  • 为什么要使用 $1 的别名?您已在声明中将其命名为 _day。坚持下去。
  • 一定要知道 PostgreSQL 如何处理 case in identifiers 。 (我只使用小写。)
  • 您只需在日期中添加/减去整数(天数)即可。

关于PostgreSQL 检查前一条记录的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10257600/

相关文章:

sql - 如何将一个字段的日期与另一字段的时间合并 - MS SQL Server

c# - 格式化 .NET DateTime "Day",不带前导零

function - 如何在 PostgreSQL 函数的插入查询中插入参数值?

Postgresql,如果存在具有某些唯一值的行则更新,否则插入

json - Postgresql group by 查询转换json格式

c++ - 在 C++ 代码中处理 PL/pgSQL 函数的消息

postgresql - 英雄联盟 "psql: FATAL: remaining connection slots are reserved for non-replication superuser connections"

postgresql - 在具有 > 12M 行的表中的 Postgresql 中查询太慢

ruby - 判断 DateTime 是否在当前时间的一小时内

arrays - 如何在函数中取消嵌套数组?