SQL:如何根据窗口框架中的聚合最小值/最大值选择列值(包括前面的行)

Posted

技术标签:

【中文标题】SQL:如何根据窗口框架中的聚合最小值/最大值选择列值(包括前面的行)【英文标题】:SQL: How to select a column-value based on an aggregate min/max value in a window frame (including preceding rows) 【发布时间】:2021-05-16 11:30:09 【问题描述】:

我有下表:

| Date     | Value   | Name | AnticipatedValue |
| -------- | ------- | ---- | ---------------- |
| 27.11.20 | 639.600 | col1 |                  |
| 30.11.20 | 638.300 | col2 |                  |
| 01.12.20 | 638.000 | col3 | col1             |
| 02.12.20 | 642.600 | col4 | col1             |
| 03.12.20 | 646.200 | col5 | col1             |
| 04.12.20 | 651.900 | col6 | col4             |
| 07.12.20 | 651.800 | col7 | col4             |
| 08.12.20 | 643.800 | col8 | col6             |
| 09.12.20 | 654.250 | col9 | col6             |

我想要 name 在第 2 和第 5 个 preceding 行之间具有最大 value 的行。 AnticipatedValue 列显示了我想要的结果。

我目前正在使用窗口函数来获取该示例中的最大值 value,但是我缺少获取该最大值 的相应 name 的方法值。 我当前的代码如下所示:

MAX(value) OVER (ORDER BY date ROWS BETWEEN 5 PRECEDING AND 2 PRECEDING)

我认为如果我能够在窗框本身的 inside 中执行另一个 ORDER BY,对我最有帮助。然后我可以使用按值降序的顺序并取我得到的名字。然而,这在 sql 的聚合函数中是不可能的/实现的。

此外,使用子查询来获取相应的名称在 imo 中也相当困难,因为我仍然必须在子查询内应用窗口框架(即前面的第 2 行和第 5 行)。

我使用的是 Postgres 12.6。

我非常感谢有关此 sql 谜题的任何帮助。我觉得我离解决方案不远了,但找不到任何优雅的方法来做到这一点。

更新 我采用了 Gordon Linoff 的解决方案并通过使用左连接并添加限制 1 来调整它以获得我想要的上表:

select t.*, t2.*
from t left join lateral
     (select t2.name, t2.value
      from (select t2.name, t2.value
            from t t2
            where t2.date < t.date
            order by t2.date desc
            offset 1 fetch first 4 rows only
           ) t2
       order by value desc
      limit 1
      ) t2 ON true;

【问题讨论】:

【参考方案1】:

您可以使用横向连接:

select t.*, t2.*
from t cross join lateral
     (select t2.*
      from (select t2.name, t2.value
            from t t2
            where t2.date < t.date
            order by t2.date desc
            offset 1 fetch first 4 rows only
           ) t2
       order by value desc
      ) t2;

  

【讨论】:

你是我认识的唯一一个在他们的答案中使用横向连接的人。太棒了。 @Gordon Linoff 这个 sql 谜语已经困扰我好几天了,当时我正在阅读各种窗口函数内容等,拼命寻找我忽略的东西。在这里,您可以使用横向交叉连接和巧妙的方式使用带有 where 子句的负偏移量 + 降序...太棒了,非常感谢!从那句话中我学到了很多东西 PS:我想没有用窗口函数解决它的优雅方法,对吧?! 所以我一直在使用这个解决方案,但意识到我的整体查询的性能大大降低(现在需要几秒钟)。有没有更有效的方法可用,或者这种查询总是相当低效?非常感谢您的任何建议

以上是关于SQL:如何根据窗口框架中的聚合最小值/最大值选择列值(包括前面的行)的主要内容,如果未能解决你的问题,请参考以下文章

sql 2005 聚合函数

SqlServer函数的聚合函数

如何根据最大值和最小值将一组 SQL 记录转换为单行?

如何根据 PySpark 中窗口聚合的条件计算不同值?

SQL Server报错:选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中

Postgres:一次选择获取最小值,最大值,聚合值