【问题标题】:Get count of values in different subgroups获取不同子组中的值计数
【发布时间】:2021-10-31 09:22:48
【问题描述】:

我需要删除数据集中的一些行,其中speed 等于零并持续 N 次(假设 N 为 2)。 表demo 的结构如下:

id car speed time
1 foo 0 1
2 foo 0 2
3 foo 0 3
4 foo 1 4
5 foo 1 5
6 foo 0 6
7 bar 0 1
8 bar 0 2
9 bar 5 3
10 bar 5 4
11 bar 5 5
12 bar 5 6

然后我希望使用window_function生成如下表:

id car speed time lasting
1 foo 0 1 3
2 foo 0 2 3
3 foo 0 3 3
4 foo 1 4 2
5 foo 1 5 2
6 foo 0 6 1
7 bar 0 1 2
8 bar 0 2 2
9 bar 5 3 4
10 bar 5 4 4
11 bar 5 5 4
12 bar 5 6 4

然后我可以使用WHERE NOT (speed = 0 AND lasting > 2)轻松排除这些行

把我试过的代码放在这里,但它没有返回我期望的值,我猜那些FROM (SELECT ... FROM (SELECT ...可能不是解决问题的最佳实践:

SELECT g3.*, count(id) OVER (PARTITION BY car, cumsum ORDER BY id) as num   
  FROM (SELECT g2.*, sum(grp2) OVER (PARTITION BY car ORDER BY id) AS cumsum             
    FROM (SELECT g1.*, (CASE ne0 WHEN 0 THEN 0 ELSE 1 END) AS grp2                            
      FROM (SELECT g.*, speed - lag(speed, 1, 0) OVER (PARTITION BY car) AS ne0              
        FROM (SELECT *, row_number() OVER (PARTITION BY car) AS grp FROM demo) g ) g1 ) g2 ) g3                                                                                       
ORDER BY id;

【问题讨论】:

    标签: postgresql count where-clause window-functions


    【解决方案1】:

    您可以使用窗口函数 LAG() 检查每行的前一个 speed 值,并使用 SUM() 窗口函数为连续值创建组。
    然后使用COUNT()窗口函数可以统计每组的行数,这样就可以过滤掉超过2行的组中speed为0的行:

    SELECT id, car, speed, time
    FROM (
      SELECT *, COUNT(*) OVER (PARTITION BY car, grp) counter
      FROM (
        SELECT *, SUM(flag::int) OVER (PARTITION BY car ORDER BY time) grp
        FROM (
          SELECT *, speed <> LAG(speed, 1, speed - 1) OVER (PARTITION BY car ORDER BY time) flag
          FROM demo
        ) t  
      ) t
    ) t
    WHERE speed <> 0 OR counter <= 2
    ORDER BY id;
    

    请参阅demo

    【讨论】:

    • 谢谢。我注意到解决方案中的另一点:请问在OVER 短语中使用ORDER BY 的时间。有时我发现查询需要ORDER BY 才能获得正确的反馈,但有时不需要。
    • @FanLiu 在所有分区的 ORDER BY 子句中使用列 time 更有意义。我使用了id,因为这是我在您的代码中看到的。
    • 完全同意使用time 字段的想法。我的问题完美解决了。非常感谢:)
    猜你喜欢
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 2016-07-06
    • 2016-11-24
    • 2015-11-14
    相关资源
    最近更新 更多