满足条件后,SQL选择每个组的所有行

时间:2020-03-25 00:15:19

标签: sql window-functions correlated-subquery

我想在最后一次满足该组的条件之后为每个组选择所有行。该related question的答案使用相关子查询。

就我而言,我将拥有数以百万计的类别和数以亿计的行。 是否有一种方法可以使用性能更高的查询获得相同的结果?

这里是一个例子。条件是条件列中最后一个0之后的所有行(每组)。

category | timestamp |  condition 
--------------------------------------
   A     |     1     |     0 
   A     |     2     |     1 
   A     |     3     |     0 
   A     |     4     |     1
   A     |     5     |     1
   B     |     1     |     0 
   B     |     2     |     1
   B     |     3     |     1

我想要实现的结果是

category | timestamp |  condition 
--------------------------------------
   A     |     4     |     1
   A     |     5     |     1
   B     |     2     |     1
   B     |     3     |     1

2 个答案:

答案 0 :(得分:1)

如果要在最后一个0之后输入所有内容,可以使用窗口函数:

select t.*
from (select t.*,
             max(case when condition = 0 then timestamp end) over (partition by category) as max_timestamp_0
      from t
     ) t
where timestamp > max_timestamp_0 or
      max_timestamp_0 is null;

(category, condition, timestamp)上有一个索引,相关的子查询版本也可能执行得很好:

select t.*
from t
where t.timestamp > all (select t2.timestamp
                         from t t2
                         where t2.category = t.category and
                               t2.condition = 0
                        );

答案 1 :(得分:1)

您可能想尝试窗口功能:

select category, timestamp, condition
from (
    select 
        t.*,
        min(condition) over(partition by category order by timestamp desc) min_cond
    from mytable t
) t
where min_cond = 1

带有min()子句的窗口order by计算同一condition的当前行和后续行中category的最小值:我们可以将其用作过滤器消除最近的行带有0的行。

与相关子查询方法相比,使用窗口函数的好处是它减少了表上所需的扫描次数。当然,这种计算也需要一定的成本,因此您需要根据样本数据评估两种解决方案。

相关问题