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:如何根据窗口框架中的聚合最小值/最大值选择列值(包括前面的行)的主要内容,如果未能解决你的问题,请参考以下文章