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

PostgreSQL:如何筛选分组中当前值组合的首次更新行

解决方案:提取分组中当前值组合的持续起始行

针对你的需求——获取每个group中当前foo/bar组合首次开始持续未变化的行(而非历史首次出现),可以通过PostgreSQL的窗口函数高效实现,无需程序遍历。

核心思路

通过窗口函数标记连续相同foo/bar组合的分组,找到每个group最新的连续分组,再取该分组的第一行(即持续起始点)。

具体SQL实现

WITH ranked_rows AS (
  SELECT
    *,
    -- 标记连续相同foo/bar的分组:当当前行与上一行值不同时,新建分组
    SUM(CASE WHEN (foo, bar) = LAG((foo, bar)) OVER (PARTITION BY "group" ORDER BY timestamp) THEN 0 ELSE 1 END)
      OVER (PARTITION BY "group" ORDER BY timestamp) AS continuous_group
  FROM foobar
),
latest_continuous_groups AS (
  -- 获取每个group最新的连续分组ID
  SELECT "group", MAX(continuous_group) AS current_group
  FROM ranked_rows
  GROUP BY "group"
)
-- 从最新连续分组中取最早的一行(即持续起始点)
SELECT DISTINCT ON (rr."group") rr.*
FROM ranked_rows rr
JOIN latest_continuous_groups lcg ON rr."group" = lcg."group" AND rr.continuous_group = lcg.current_group
ORDER BY rr."group", rr.timestamp ASC;

针对示例数据的执行结果

对于你提供的示例数据,该查询会返回:

+------+---------+-------+-------+-------------+------------------+
| "id" | "group" | "foo" | "bar" | "timestamp" | "continuous_group" |
+------+---------+-------+-------+-------------+------------------+
| 3    | 1       | 10    | 20    | 3           | 3                |
+------+---------+-------+-------+-------------+------------------+

这正是(10,20)组合开始持续未变化的起始行。

优化建议

为提升查询效率,建议创建复合索引:

CREATE INDEX idx_foobar_group_timestamp ON foobar ("group", timestamp);

该索引会加速窗口函数中的分组排序操作,尤其在数据量较大时效果明显。

特殊情况处理

如果某个group所有行的foo/bar组合完全相同,该查询会自动返回该分组的第一行(即首次出现的行,因为全程未变化),符合需求逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 13:33:32