首页 > 数据库 > mysql教程 > 如何在 PostgreSQL 中高效统计某个时间范围内的前行数?

如何在 PostgreSQL 中高效统计某个时间范围内的前行数?

Linda Hamilton
发布: 2024-12-27 07:27:12
原创
467 人浏览过

How to Efficiently Count Preceding Rows Within a Time Range in PostgreSQL?

计算范围内的前一行

问题陈述:

确定定义时间内先前记录的总数表中每一行的范围。

特定场景:

查询:

SELECT id, date
     , count(*) OVER (HAVING previous_rows.date >= (date - '1 hour'::interval))  -- ?
FROM test;
登录后复制

表:

CREATE TABLE test (
  id  bigint
, ts  timestamp
);
登录后复制

Postgres 11 或更高版本:

Postgres 11 引入了改进的窗口函数框架选项,允许使用 RANGE使用 PRECEDING 和 FOLLOWING 的模式来选择指定偏移量内的行。

SELECT id, ts
     , count(*) OVER (ORDER BY ts RANGE '1 hour' PRECEDING EXCLUDE CURRENT ROW)
FROM   test
ORDER  BY ts;
登录后复制

Postgres 10 或更早版本:

ROM(Roman 的查询):

SELECT id, ts
     , (SELECT count(*)::int - 1
        FROM   unnest(dates) x
        WHERE  x >= sub.ts - interval '1h') AS ct
FROM (
   SELECT id, ts
        , array_agg(ts) OVER(ORDER BY ts) AS dates
   FROM   test
   ) sub;
登录后复制

ARR (计算数组元素):

SELECT id, ts
     , (SELECT count(*)
        FROM   test t1
        WHERE  t1.ts >= t.ts - interval '1h'
        AND    t1.ts < t.ts) AS ct
FROM   test t
ORDER  BY ts;
登录后复制

COR(相关子查询):

CREATE OR REPLACE FUNCTION running_window_ct(_intv interval = '1 hour')
  RETURNS TABLE (id bigint, ts timestamp, ct int)
  LANGUAGE plpgsql AS
$func$
DECLARE
   cur   CURSOR FOR
         SELECT t.ts + _intv AS ts1
              , row_number() OVER (ORDER BY t.ts ROWS UNBOUNDED PRECEDING) AS rn
         FROM   test t
         ORDER  BY t.ts;
   rec   record;
   rn    int;
BEGIN
   OPEN cur;
   FETCH cur INTO rec;
   ct := -1;  -- init

   FOR id, ts, rn IN
      SELECT t.id, t.ts
           , row_number() OVER (ORDER BY t.ts ROWS UNBOUNDED PRECEDING)
      FROM   test t ORDER BY t.ts
   LOOP
      IF rec.ts1 >= ts THEN
         ct := ct + 1;
      ELSE
         LOOP
            FETCH cur INTO rec;
            EXIT WHEN rec.ts1 >= ts;
         END LOOP;
         ct := rn - rec.rn;
      END IF;

      RETURN NEXT;
   END LOOP;
END
$func$;
登录后复制

调用函数:

SELECT * FROM running_window_ct();
登录后复制

基准结果:

使用具有不同行数的表进行的基准测试表明,FNC 函数在性能和可扩展性方面明显胜出。

以上是如何在 PostgreSQL 中高效统计某个时间范围内的前行数?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板