【问题标题】:SQL select all rows per group after a condition is metSQL 在满足条件后选择每组的所有行
【发布时间】:2020-03-25 00:15:19
【问题描述】:

我想在最后一次满足该组的条件后选择每个组的所有行。这个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

【问题讨论】:

  • 你想满足什么条件?
  • @GordonLinoff 在示例中,它的所有行都在最后一个 0 之后。我将更新问题

标签: sql window-functions correlated-subquery


【解决方案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
                        );

【讨论】:

  • 感谢您,如果可以,您可以扩展每种方法的性能影响吗?
【解决方案2】:

您可能想尝试窗口函数:

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

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

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

【讨论】:

  • 感谢关于性能的讨论和我只需要尝试的最终建议 :) 在这种情况下似乎没有灵丹妙药“这是最好的方法”。
猜你喜欢
  • 2021-11-04
  • 2021-08-08
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
  • 2019-12-24
  • 2019-04-24
  • 2014-02-18
  • 1970-01-01
相关资源
最近更新 更多