【问题标题】:different data window for FIRST_VALUE and LAST_VALUEFIRST_VALUE 和 LAST_VALUE 的不同数据窗口
【发布时间】:2018-09-08 07:45:25
【问题描述】:

以下查询给出了奇怪的结果。看起来 FIRST_VALUE 的默认窗口始终是 UNBOUNDED PRECEDING 和 UNBOUNDED FOLLOWING,而 LAST_VALUE 的默认窗口类似于 CURRENT_ROW 和 CURRENT_ROW。这是为什么呢?

select 
to_char(INVOICEDATE,'iw') WEEK,
SUM(total) AS TOTAL_SUM,

FIRST_VALUE(to_char(INVOICEDATE,'iw')) OVER (order by SUM(total)) minimum,
FIRST_VALUE(to_char(INVOICEDATE,'iw')) OVER (order by SUM(total) DESC) maximum,
LAST_VALUE(to_char(INVOICEDATE,'iw')) OVER (order by SUM(total)) max_2,
LAST_VALUE(to_char(INVOICEDATE,'iw')) OVER (order by SUM(total) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) max_3

from invoice

WHERE to_char(INVOICEDATE,'iw') < 9
group by to_char(INVOICEDATE,'iw')
order by to_char(INVOICEDATE,'iw')

结果如下:

【问题讨论】:

  • BETWEEN CURRENT_ROW AND CURRENT_ROW 将是只是当前行,我不认为是这种情况。
  • 是的,但是“max_2”的行为方式是这样的..
  • 检查documentation如果您完全省略了windowing_clause,则默认为RANGE BETWEEN UNBoundED PRECEDING AND CURRENT ROW。
  • 请不要以图片形式提供结果,以文字形式提供。此外,如果没有您的源数据,也很难为您提供帮助。
  • 但如果是这样,为什么两个 FIRST_VALUE 对所有行都显示相同的结果?每个 LAST_VALUE 都不一样,抱歉,我不明白 :)

标签: sql oracle


【解决方案1】:

如果您一次查看一个计算列,并按照over 子句的顺序对输出进行排序,您可能会发现更容易了解正在发生的事情。

仅针对第一个最小值,按总计排序:

select 
  to_char(invoicedate,'iw') week,
  sum(total) as total_sum,
  first_value(to_char(invoicedate,'iw')) over (order by sum(total)) minimum
from invoice
where to_char(invoicedate,'iw') < 9
group by to_char(invoicedate,'iw')
order by total_sum;

WEEK  TOTAL_SUM MINIMUM
---- ---------- -------
08         30.7 08     
04        34.65 08     
01        35.65 08     
03        38.66 08     
05        41.58 08     
06        56.43 08     
07        59.48 08     
02        63.45 08     

您使用的排序(在over() 中)意味着first_value 处理的第一行是08,因此它可以看到自己。该排序中的第二行是第 04 周,但它考虑行 unbounded preceding to current row,因此它查看 08 和 04,并采用 08,因为它仍然是(并且始终按该排序)首先。以此类推。

仅对于第一个最大值,按总降序排列:

select 
  to_char(invoicedate,'iw') week,
  sum(total) as total_sum,
  first_value(to_char(invoicedate,'iw')) over (order by sum(total) desc) maximum
from invoice
where to_char(invoicedate,'iw') < 9
group by to_char(invoicedate,'iw')
order by total_sum desc;

WEEK  TOTAL_SUM MAXIMUM
---- ---------- -------
02        63.45 02     
07        59.48 02     
06        56.43 02     
05        41.58 02     
03        38.66 02     
01        35.65 02     
04        34.65 02     
08         30.7 02     

这与前一个相反;使用该顺序看到的第一行是第 02 周;第二行考虑 02 和 07 并使用 02,因为它仍然是(并且始终按该顺序)。

仅用于最后一个最大值,按总计排序:

select 
  to_char(invoicedate,'iw') week,
  sum(total) as total_sum,
  last_value(to_char(invoicedate,'iw')) over (order by sum(total)) max_2
from invoice
where to_char(invoicedate,'iw') < 9
group by to_char(invoicedate,'iw')
order by total_sum;

WEEK  TOTAL_SUM MAX_2  
---- ---------- -------
08         30.7 08     
04        34.65 04     
01        35.65 01     
03        38.66 03     
05        41.58 05     
06        56.43 06     
07        59.48 07     
02        63.45 02     

现在,行的顺序与前一个块不同。具有该顺序的第一行又回到了 08,我们仍然使用默认的 window 子句,所以只能使用那个。

第二行是04周,只能考虑08和04; 按该顺序 04 现在是最后看到的值。这对于所有后续行都是相同的;由于排序,最后看到的值是该行。

窗口是相同的,但您使用的顺序会影响该窗口中实际存在的行。对于您的max_3 计算,您正在更改窗口以包含所有行;您还可以反转默认窗口,使其(有点,有效地)匹配用于first_rows 的窗口:

  last_value(to_char(invoicedate,'iw')) over (order by sum(total)
    rows between current row and unbounded following) max_3

【讨论】:

  • 非常感谢您提供如此出色而完整的答案!
【解决方案2】:

哦,我现在明白了。 这两个函数都有像 UNBOUNDED PRECEDING 和 CURRENT ROW 这样的窗口,但是 FIRST_VALUE 获得第一行,所以无论有多少跟随它总是显示第一个结果,而 LAST_VALUE 总是显示 CURRENT_ROW。 谢谢大家!

【讨论】:

  • 但在您的示例中,FIRST_VALUE 列显示不同的输出:0802。如果您对第一个使用ASC 排序,对第二个使用DESC,这是预期的结果。也许你应该编辑你的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多