Sql Oracle LAST_值仅在分析子句中带有order by

Sql Oracle LAST_值仅在分析子句中带有order by,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,我有架构(Oracle 11g R2): 我执行以下查询-仅使用orderby分析子句使用LAST\u VALUE分析函数: 我的假设是,这个查询在一个分区上执行—整个表(因为缺少partition by子句)。它将按给定分区(整个表)中的名称对行进行排序,并将使用默认窗口子句在无界的前一行和当前行之间的范围 select us.*, last_value(num) over (order by name) as lv from users us; 但上面执行的查询将给出与下面的查询完全相

我有架构(Oracle 11g R2):

我执行以下查询-仅使用
orderby
分析子句使用
LAST\u VALUE
分析函数:

我的假设是,这个查询在一个分区上执行—整个表(因为缺少partition by子句)。它将按给定分区(整个表)中的名称对行进行排序,并将使用默认窗口子句
在无界的前一行和当前行之间的范围

select us.*, 
last_value(num) over (order by name) as lv 
from users us;
但上面执行的查询将给出与下面的查询完全相同的结果。关于第二个查询,我的假设是,该查询首先按名称对表行进行分区,然后按num对每个分区中的行进行排序,然后在每个分区上应用windowing子句
在无界前向和无界后向之间的范围
,以获得
最后一个值

select us.*, 
last_value(num) over (partition by name order by num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lv 
from users us;
我的一个假设显然是错误的,因为上面提到的两个查询给出了相同的结果。看起来第一个查询也是按num排序的。你能告诉我我的假设有什么问题吗?为什么这些查询会返回相同的结果

select us.*,
       last_value(num) over (order by name) as lv
from users us;

在Oracle杂志中,如果在窗口函数中使用
ORDER BY
子句而不指定任何其他内容,则会发生以下情况:

ORDER BY子句在没有任何进一步的窗口子句参数的情况下,有效地添加了一个默认窗口子句:RANGE UNBONDED PREVICE,这意味着“当前分区中的当前行和以前的行是计算中应该使用的行。”当ORDER BY子句没有随附分区子句时,分析函数使用的整组行是默认的当前分区

因此,您的第一个查询实际上与此相同:

SELECT us.*, LAST_VALUE(num) OVER (ORDER BY name RANGE UNBOUNDED PRECEDING) AS lv
FROM users us;
如果运行上述查询,您将获得当前看到的行为,这将为每个名称返回一个单独的last值。这与以下查询不同:

SELECT
    us.*,
    LAST_VALUE(num) OVER (ORDER BY name
        RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS lv
FROM users us;
这只会为num的最后一个值生成值
8
,该值对应于
matej
的值,在对名称升序排序时,matej是姓氏。

是一个dbfiddle,以防有人想玩它们

假设您认为第二个查询返回了正确的结果

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;
范围在这里非常重要。它不会转到当前行。它将转到
name
中具有相同值的所有行

根据我对
orderby
文档的理解,可以从同名行中选择任何
num
值。为什么?SQL(和Oracle)中的排序不稳定。这意味着不能保证保留行的原始顺序


在这种特殊情况下,最后一个值恰好是最大值可能是巧合。或者,出于某种原因,Oracle可能出于某种原因将
num
添加到订单中。

答案很简单。无论出于何种原因,Oracle选择在windowing子句中使用逻辑
范围
)偏移量时(默认情况下,显式或隐式)确定
最后一个\u值。具体地说,在这种情况下,测量表达式的最高值是从一组行中选择的,这些行通过排序进行排序

在Oracle文档中该页的底部,我们可以看到:

当为
ORDER BY
表达式找到重复项时,
LAST\u值
是expr[…]的最高值


为什么文档在示例部分中说了这一点,而不是在功能说明中?因为,通常情况下,文档似乎不是由合格人员编写的。

谢谢您的回答。我进行了多次尝试,但似乎并不是巧合,因为始终选择正确的值作为最后的值。我同意num的订购似乎是出于某种原因执行的,但找不到任何官方信息来支持这一说法。顺便说一句,您简洁编写的第二个查询不会返回与第一个查询相同的行集。您必须省略“order by”,因为这会引入默认窗口(并且在使用“max”分析函数时也没有效果)@EddGarcia。我意识到这一点。我无法解释那种行为。然而,“正确值”并不是最高值;相同名称的任何值都是等效的。选择最高值似乎是甲骨文工作方式的产物。我强烈建议您为此目的使用
MAX()
。“在我阅读本文时”,您说。在哪里读书?你在那之后所说的是非常明智的(一个非常好的假设),但你没有在任何地方读到它。事实上,Oracle文档的说法正好相反;Oracle选择在windowing子句中使用
range
时使函数具有确定性。他们总是从并列的行中选择最大的值来实现这一点。@mathguy。你有这方面的参考资料吗?是的,我刚刚发布了它。所有这些可能都是正确的,但它甚至与OP的问题没有任何重叠,OP的问题是:为什么第一个查询返回的结果似乎使用了平分符?就好像
order by
子句是
order by name,num
。这个问题有一个非常简单的答案,但它不是你给出的。@mathguy
,它将使用默认的windowing子句范围,介于无界的前一行和当前行之间
。。。事实上,我的回答确实解决了OP的一些疑问。他引用的窗口不是默认窗口,这解释了OP当前的观察结果。。。你是妈妈