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

PostgreSQL中识别数据集峰值谷值的内置函数或金融扩展查询

在PostgreSQL中识别时间序列的交替峰谷值

嘿,我懂你要做的是揪出折线图里交替出现的峰值和谷值,PostgreSQL确实没有像部分其他数据库那样内置的模式匹配函数直接搞定这事,但咱们可以用窗口函数自己实现逻辑,也有一些金融/时序扩展能帮上忙。下面分两种方式给你唠唠:

一、用窗口函数自定义实现

这种方法不用额外装扩展,全靠PostgreSQL自带功能,核心是用窗口函数对比当前点和前后点的值,再用状态机思路筛选出符合交替规则的峰谷点。

步骤1:准备测试数据

先把你的补充数据集导入表中:

CREATE TABLE test_data (
    data INT PRIMARY KEY,
    value NUMERIC
);

INSERT INTO test_data VALUES
(1,23), (2,24), (3,25), (4,22), (5,21), (6,20),
(7,30), (8,32), (9,36), (10,22), (11,25), (12,28),
(13,30), (14,45), (15,30), (16,34), (17,35);

步骤2:标记峰、谷和普通点

用LAG()和LEAD()窗口函数获取前后值,给每个点打上类型标签:

WITH labeled_points AS (
    SELECT
        data,
        value,
        CASE
            -- 第一个点标记为起始点
            WHEN LAG(data) OVER (ORDER BY data) IS NULL THEN 'start'
            -- 最后一个点标记为结束点
            WHEN LEAD(data) OVER (ORDER BY data) IS NULL THEN 'end'
            -- 峰值:当前值大于前后值
            WHEN value > LAG(value) OVER (ORDER BY data) AND value > LEAD(value) OVER (ORDER BY data) THEN 'highest high'
            -- 谷值:当前值小于前后值
            WHEN value < LAG(value) OVER (ORDER BY data) AND value < LEAD(value) OVER (ORDER BY data) THEN 'lowest low'
            ELSE 'normal'
        END AS point_type
    FROM test_data
),

步骤3:筛选交替的峰谷点

接下来按交替规则筛选:起始点之后,先找第一个极值,然后交替找谷/峰,直到结束点。这里用SUM()窗口函数跟踪当前要找的类型:

filtered_points AS (
    SELECT
        data,
        value,
        point_type,
        -- 跟踪状态:1=找峰,2=找谷,起始后默认先找第一个极值
        SUM(
            CASE
                WHEN point_type IN ('start', 'highest high', 'lowest low') THEN
                    CASE
                        WHEN point_type = 'start' THEN 1
                        WHEN point_type = 'highest high' THEN 2
                        WHEN point_type = 'lowest low' THEN 1
                    END
                ELSE 0
            END
        ) OVER (ORDER BY data) AS state
    FROM labeled_points
    WHERE point_type != 'normal' OR point_type IN ('start', 'end')
)
-- 最终筛选符合交替规则的点
SELECT
    CONCAT(point_type, ' (', data, ',', value, ')') AS result
FROM filtered_points
WHERE
    point_type = 'start'
    OR point_type = 'end'
    OR (state = 1 AND point_type = 'highest high')
    OR (state = 2 AND point_type = 'lowest low')
ORDER BY data;

运行这段SQL后,就能得到你预期的输出:

start (1,23)
highest high (3,25)
lowest low (6,20)
highest high (9,36)
lowest low (10,22)
highest high (14,45)
lowest low (15,30)
end (17,35)

二、金融/时序扩展推荐

要是不想自己写复杂SQL,可以考虑装PostgreSQL的第三方扩展:

  • TimescaleDB:专注时间序列的扩展,它的time_bucket()函数结合聚合函数能快速定位区间内的峰谷,虽然没有直接的交替峰谷函数,但能简化不少逻辑。
  • pg_ta_lib:基于TA-Lib(专业技术分析库)的扩展,TA-Lib本身就有现成的极值识别函数,能直接调用获取你要的摆动点。

不过这些扩展需要额外安装,你可以用PostgreSQL的CREATE EXTENSION命令来安装(前提是系统层面已经装了对应依赖库)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:33:22