获取不同子组中的值计数

Posted

技术标签:

【中文标题】获取不同子组中的值计数【英文标题】: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;

【问题讨论】:

【参考方案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 字段的想法。我的问题完美解决了。非常感谢:)

以上是关于获取不同子组中的值计数的主要内容,如果未能解决你的问题,请参考以下文章

计算不同时间段内子组的数据框中的百分比变化

sql 封装子组中的子查询数据

SQL - 组的子组中的期间范围

获取组的所有子组[重复]

DB2:需要获取给定db2表的列列表和不同的值计数

SQL Server:计算组中的不同日期