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

纯SQL实现:统计最后一个0之后的1的数量及Amount列求和(高效查询)

解决方案:用窗口函数实现单次扫描的高效统计

这是个很常见的业务统计需求,而且要求仅访问一次数据保证效率,我们可以利用窗口函数来精准定位最后一个flag=0的位置,再筛选后续符合条件的记录完成统计,全程只需要扫描一次表。

核心SQL代码

SELECT
    COUNT(*) AS count_1,
    SUM(amount) AS sum_amount
FROM (
    SELECT
        flag,
        amount,
        -- 标记当前记录是否处于最后一个0之后的区间
        CASE 
            WHEN MAX(CASE WHEN flag = 0 THEN id END) OVER () < id 
            THEN 1 
            ELSE 0 
        END AS is_after_last_0
    FROM your_table
) t
WHERE is_after_last_0 = 1 AND flag = 1
-- 若最后一条记录是0,或最后一个0之后没有1,结果会返回空,符合需求

代码细节解释

  1. 子查询逻辑:

    • MAX(CASE WHEN flag = 0 THEN id END) OVER ():通过窗口函数MAX()结合全局窗口OVER(),计算出整个表中最后一条flag=0记录的主键id(如果你的表是按时间排序,把id换成时间字段比如create_time即可)。
    • 用CASE判断当前记录的id是否大于这个最后一个0的id,是则标记为1,代表这条记录在最后一个0之后。
  2. 外层统计逻辑:

    • 筛选出is_after_last_0=1且flag=1的记录,直接统计数量和金额总和。
    • 如果最后一条记录本身就是flag=0,那么MAX(CASE WHEN flag=0 THEN id END)就是最后一条记录的id,此时没有记录的id会大于它,外层查询自然返回空结果,完美符合需求。

适配时间排序场景

如果你的数据是按时间顺序而非主键排序,只需要替换排序字段即可:

SELECT
    COUNT(*) AS count_1,
    SUM(amount) AS sum_amount
FROM (
    SELECT
        flag,
        amount,
        CASE 
            WHEN MAX(CASE WHEN flag = 0 THEN create_time END) OVER () < create_time 
            THEN 1 
            ELSE 0 
        END AS is_after_last_0
    FROM your_table
) t
WHERE is_after_last_0 = 1 AND flag = 1

验证示例数据

用你给出的示例数据测试:

FlagAmountid
051
182
0103
1204
1305

子查询中MAX(CASE WHEN flag=0 THEN id END)的结果是3,所以id=4和id=5的is_after_last_0为1,且它们的flag=1,外层统计后得到count_1=2,sum_amount=50,和预期完全一致。

如果最后一条记录是0,比如:

FlagAmountid
051
182
0103

此时MAX(CASE WHEN flag=0 THEN id END)是3,没有记录的id大于3,外层查询返回空结果,符合要求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:41:41