sql - 窗口函数 : last_value(ORDER BY . .. ASC) 与 last_value(ORDER BY ... DESC) 相同

标签 sql postgresql window-functions

示例数据

CREATE TABLE test
    (id integer, session_ID integer, value integer)
;

INSERT INTO test
    (id, session_ID, value)
VALUES
    (0, 2, 100),
    (1, 2, 120),
    (2, 2, 140),
    (3, 1, 900),
    (4, 1, 800),
    (5, 1, 500)
;

当前查询

select 
id,
last_value(value) over (partition by session_ID order by id) as last_value_window,
last_value(value) over (partition by session_ID order by id desc) as last_value_window_desc
from test
ORDER BY id

我遇到了 last_value() 窗口函数的问题: http://sqlfiddle.com/#!15/bcec0/2

在 fiddle 中,我尝试在 last_value() 查询中使用排序方向。

编辑: 问题不是:为什么我没有得到所有时间的最后一个值以及如何使用 frame 子句(unbounded precedingunbounded following)。我知道 first_value(desc)last_value() 的区别以及 last_value() 没有给你所有时间的问题最后一个值:

默认框架子句在当前行之前是无界的。所以第一个值总是给出带有子句的第一行。因此,只有一行(框架子句只包括这一行)还是一排(框架子句包括所有一百)都没有关系。结果总是第一个。在 DESC 顺序中,它是相同的:DESC 更改排序顺序,然后第一行是最后一个值,无论您获得多少行。

last_value() 的行为非常相似:如果你有一行,它会为你提供默认框架子句的最后一个值:这一行。在第二行,框架子句包含两行,最后一行是第二行。这就是为什么 last_value() 不会为您提供所有行的最后一行,而只会为您提供当前行之前的最后一行。

但是,如果我将顺序更改为 DESC,我希望所有的最后一行排在第一位,所以我在第一行得到这个,而不是第二行的最后一行,依此类推。但这不是结果。为什么?

对于当前示例,这些是 first_value()first_value(desc)last_value()last_value 的结果(desc) 以及我对 last_value(desc) 的期望:

 id | fv_asc | fv_desc | lv_asc | lv_desc | lv_desc(expecting)
----+--------+---------+--------+---------+--------------------
  0 |    100 |     140 |    100 |     100 |    140
  1 |    100 |     140 |    120 |     120 |    120
  2 |    100 |     140 |    140 |     140 |    100
  3 |    900 |     500 |    900 |     900 |    500
  4 |    900 |     500 |    800 |     800 |    800
  5 |    900 |     500 |    500 |     500 |    900

对我来说,ORDER BY DESC 标志在默认框架子句 last_value() 调用中似乎被忽略了。但它不在 first_value() 调用中。所以我的问题是:为什么 last_value() 结果与 last_value(desc) 相同?

最佳答案

LAST_VALUE() 的问题是窗口子句的默认规则删除了您真正想要的值。这是一个非常微妙的问题,在所有支持此功能的数据库中都是如此。

This来自 Oracle 博客:

Whilst we are on the topic of windowing clauses, the implicit and unchangeable window clause for the FIRST and LAST functions is ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING, in other words all rows in our partition. For FIRST_VALUE and LAST_VALUE the default but changeable windowing clause is ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, in other words we exclude rows after the current one. Dropping rows off the bottom of a list makes no difference when we are looking for the first row in the list (FIRST_VALUE) but it does make a difference when we are looking for the last row in the list (LAST_VALUE) so you will usually need either to specify ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING explicitly when using LAST_VALUE or just use FIRST_VALUE and reverse the sort order.

因此,只需使用 FIRST_VALUE()。这做你想要的:

with test (id, session_ID, value) as (
      (VALUES (0, 2, 100),
              (1, 2, 120),
              (2, 2, 140),
              (3, 1, 900),
              (4, 1, 800),
              (5, 1, 500)
      )
     )
select id,
       first_value(value) over (partition by session_ID order by id) as first_value_window,
       first_value(value) over (partition by session_ID order by id desc) as first_value_window_desc
from test
order by id

关于sql - 窗口函数 : last_value(ORDER BY . .. ASC) 与 last_value(ORDER BY ... DESC) 相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42299101/

相关文章:

sql - Postgresql更新字符串,前后添加字符

sql - SQL唯一组合

node.js - winston postgresql 自定义 sql/tableName 不工作

MySQL NOT IN 返回错误的数字

matlab - 来自 PostgreSQL 的 Octave 数据库包时间戳

sql - T-SQL LAG 函数默认值

mysql - 在 MySQL 中对结果进行排名时如何处理平局?

sql - 获取 Oracle 上每个值的第二大最大值

php - 查询树的项目数

sql - 如何使用 SQL 计算列中非连续值的数量?