You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL提取同ID&Dir且30分钟内dist最大值记录

PostgreSQL 筛选同ID/Dir且30分钟内记录并取Dist最大值行

问题描述

从table_1表提取数据:筛选id与dir列值相同、datetime处于30分钟时间范围内的记录组,获取每个组内dist列值最大的完整行数据。

建表语句(参考)

CREATE TABLE table_1 (
    id INT,
    dir VARCHAR(50),
    datetime TIMESTAMP,
    dist NUMERIC,
    other_cols TEXT -- 其他业务列
);

解决方案

根据时间范围的定义(滑动窗口/固定窗口),提供两种常用实现方式:

方式1:滑动时间窗口(同ID/Dir下,任意记录datetime差≤30分钟为一组)

使用窗口函数的RANGE子句定义滑动时间范围,直接标记每组内的最大dist行:

WITH ranked_records AS (
    SELECT
        *,
        -- 按ID、Dir分组,在当前记录前后30分钟窗口内按dist降序排名
        ROW_NUMBER() OVER (
            PARTITION BY id, dir
            ORDER BY dist DESC
            RANGE BETWEEN INTERVAL '30 minutes' PRECEDING AND INTERVAL '30 minutes' FOLLOWING
        ) AS rank_num
    FROM table_1
)
-- 取每个窗口内排名第一的行(即dist最大的行)
SELECT id, dir, datetime, dist, other_cols
FROM ranked_records
WHERE rank_num = 1;

方式2:固定30分钟窗口(按整点/半点划分固定时间窗口)

如果需求是将时间按每30分钟的固定区间分组(如10:00-10:30、10:30-11:00),可通过截断时间生成窗口标识:

WITH window_groups AS (
    SELECT
        *,
        -- 生成30分钟窗口的起始时间(如10:15→10:00,10:40→10:30)
        DATE_TRUNC('minute', datetime) - INTERVAL '1 minute' * (EXTRACT(minute FROM datetime)::INT % 30) AS window_start
    FROM table_1
),
ranked_in_group AS (
    SELECT
        *,
        -- 按ID、Dir、窗口起始时间分组,取dist最大的行
        ROW_NUMBER() OVER (PARTITION BY id, dir, window_start ORDER BY dist DESC) AS rank_num
    FROM window_groups
)
SELECT id, dir, datetime, dist, other_cols
FROM ranked_in_group
WHERE rank_num = 1;

关键说明

  • 若原CTE关联查询失效,通常是因为未正确处理时间范围的分组逻辑,窗口函数能更直观地实现“分组-排序-取最值”的需求。
  • 使用ROW_NUMBER()会在dist相同时随机取一行,若需保留所有dist最大值的行,可替换为RANK()。

内容的提问来源于stack exchange,提问作者RKIDEV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:29:59