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

Oracle SQL中查找数字序列的低-高-低模式

用Oracle SQL查找“低-高-低”模式的连续序列

首先咱们得明确要找的**低-高-低(LHD)**模式的核心:一段连续数字序列里,必须先出现至少一次上升(当前数 < 下一个数),之后跟着至少一次下降(当前数 > 下一个数)。简单说就是趋势先升后降,而且升和降都不能少——像开头的4,2只有下降,6,5,1只有下降,都不符合;而2,3,6,5,1(先升两次再降两次)、3,4,2(先升一次再降一次)就完全符合要求。

下面是具体的Oracle SQL实现方案,我会一步步拆解逻辑:

步骤1:构建带行号的序列数据集

首先得把原始数字序列转换成带行号的表(行号rn是关键,确保我们能按原始顺序处理数据):

WITH seq AS (
    SELECT 4 AS num, 1 AS rn FROM dual UNION ALL
    SELECT 2, 2 FROM dual UNION ALL
    SELECT 3, 3 FROM dual UNION ALL
    SELECT 6, 4 FROM dual UNION ALL
    SELECT 5, 5 FROM dual UNION ALL
    SELECT 1, 6 FROM dual UNION ALL
    SELECT 3, 7 FROM dual UNION ALL
    SELECT 4, 8 FROM dual UNION ALL
    SELECT 2, 9 FROM dual
),

步骤2:计算每个位置的趋势

接下来用LEAD分析函数,计算每个数字和下一个数字的关系(上升UP/下降DOWN),同时用LAG拿到前一个位置的趋势,方便判断阶段变化:

trend_data AS (
    SELECT 
        num, rn,
        LEAD(num) OVER (ORDER BY rn) AS next_num,
        CASE 
            WHEN num < LEAD(num) OVER (ORDER BY rn) THEN 'UP'
            WHEN num > LEAD(num) OVER (ORDER BY rn) THEN 'DOWN'
            ELSE 'EQUAL' -- 题目里没有相等情况,可忽略
        END AS trend,
        LAG(CASE 
                WHEN num < LEAD(num) OVER (ORDER BY rn) THEN 'UP'
                WHEN num > LEAD(num) OVER (ORDER BY rn) THEN 'DOWN'
                ELSE 'EQUAL'
            END) OVER (ORDER BY rn) AS prev_trend
    FROM seq
),

步骤3:标记上升阶段的起始点

我们需要找到所有上升阶段的开始位置——也就是当趋势从非UP变成UP的位置,或者第一个出现UP的位置:

block_starts AS (
    SELECT rn AS start_rn
    FROM trend_data
    WHERE (prev_trend IS NULL OR prev_trend != 'UP') AND trend = 'UP'
),

步骤4:确定每个块的结束点

对每个上升起始点,找到对应的下降阶段的结束位置:也就是直到趋势不再是DOWN的前一个位置,同时确保这个块里确实存在下降阶段(否则不符合LHD模式):

block_ends AS (
    SELECT 
        bs.start_rn,
        MIN(CASE WHEN td.trend != 'DOWN' THEN td.rn ELSE NULL END) - 1 AS end_rn
    FROM block_starts bs
    JOIN trend_data td ON td.rn >= bs.start_rn
    GROUP BY bs.start_rn
    HAVING MIN(CASE WHEN td.trend = 'DOWN' THEN td.rn ELSE NULL END) IS NOT NULL
)

步骤5:提取并拼接符合条件的序列

最后用LISTAGG函数把每个块内的数字按顺序拼接成字符串,得到最终结果:

SELECT 
    LISTAGG(num, ',') WITHIN GROUP (ORDER BY rn) AS lhd_sequence
FROM seq
JOIN block_ends be ON seq.rn BETWEEN be.start_rn AND be.end_rn
GROUP BY be.start_rn, be.end_rn;

运行结果

执行这段SQL后,会得到你想要的两个序列:

LHD_SEQUENCE
-------------------
2,3,6,5,1
3,4,2

这个方案完美覆盖了你提到的判断逻辑:无论是多段上升后多段下降的长序列,还是单升单降的短序列,都能准确识别出来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:52:16