我有架构(Oracle 11g R2):
CREATE TABLE用户( id INT NOT NULL, name VARCHAR(30)NOT NULL, num int NOT NULL);
INSERT INTO用户(id,name,num)VALUES(1,‘alan’,5);INSERT INTO用户(id,…
答案很简单。无论出于何种原因,Oracle都选择了 LAST_VALUE 确定性的时候 的 合乎逻辑 强> ( RANGE )在窗口子句中使用offset(显式或隐式 - 默认情况下)。具体地说,在这种情况下,测量表达式的HIGHEST值是从一组行绑定的行中选择的 order by 排序。
LAST_VALUE
RANGE
order by
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/LAST_VALUE.html#GUID-A646AF95-C8E9-4A67-87BA-87B11AEE7B79
在Oracle文档的页面底部,我们可以阅读:
找到重复项时 ORDER BY 表达, LAST_VALUE 是最高价值 EXPR [...]
ORDER BY
为什么文档说的是 的 例子 强> 部分,而不是在功能的解释?因为,通常情况下,文档似乎并不是由合格的人员编写的。
这里 是一个db<>小提琴,以防有人想和他们一起玩。
我假设您认为第二个查询返回正确的结果。
select us.*, last_value(num) over (partition by name order by num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) as lv from users us;
我还要指出,这更简洁地写成:
select us.*, max(num) over (partition by name order by num ) as lv from users us;
这与你的问题无关,但我想指出来。
现在,为什么会给出相同的结果呢?
select us.*, last_value(num) over (order by name) as lv from users us;
好吧,没有窗口条款,这相当于:
select us.*, last_value(num) over (order by name range between unbounded preceding and current row ) as lv from users us;
该 range 在这里非常重要。它不会转到当前行。它去了 所有 具有相同值的行 name 。
range
name
在我对周围文档的理解中 order by , 任何 num 可以选择具有相同名称的行中的值。为什么? SQL(以及Oracle)中的排序不稳定。这意味着无法保证保留行的原始顺序。
num
在这种特殊情况下,最后一个值恰好是最大值可能是巧合。或者,由于某些原因,Oracle可能会添加 num 由于某种原因订购。
从 这个博客 在Oracle杂志中,如果你使用的话会发生这种情况 ORDER BY 窗口函数中的子句没有指定任何其他内容:
在没有任何进一步的窗口子句参数的情况下,ORDER BY子句有效地添加了一个默认的窗口子句:RANGE UNBOUNDED PRECEDING,这意味着,当前分区中的当前行和前一行是应该在计算中使用的行。当ORDER BY子句没有PARTITION子句时,分析函数使用的整个行集是默认的当前分区。
所以,你的第一个查询实际上与此相同:
SELECT us.*, LAST_VALUE(num) OVER (ORDER BY name RANGE UNBOUNDED PRECEDING) AS lv FROM users us;
如果运行上述查询,您将获得您正在看到的当前行为,这将为每个名称返回单独的最后一个值。这与以下查询不同:
SELECT us.*, LAST_VALUE(num) OVER (ORDER BY name RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS lv FROM users us;
这只会产生价值 8 对于num的最后一个值,它对应于的值 matej ,谁是排序名称升序时的姓氏。
8
matej