LAST_VALUE() 究竟是如何工作的?

Posted

技术标签:

【中文标题】LAST_VALUE() 究竟是如何工作的?【英文标题】:How exactly LAST_VALUE() works? 【发布时间】:2020-01-25 00:43:57 【问题描述】:

根据定义: LAST_VALUE() 函数是一个窗口函数,它返回结果集的有序分区中的最后一个值。

所以在我的示例中,我需要根据 QuoteID 获取最后一个 ExpirationDate 日期。

使用由QuoteID DESC 排序的FIRST_VALUE() 会产生正确的结果。

所以我期望使用由QuoteID ASC 订购的LAST_VALUE() 应该会产生相同的结果。

但是它给了我不正确的结果。

我错过了什么吗?

  DECLARE @Table TABLE ( QuoteID int, PolicyNumber varchar(100), ExpirationDate date)
 INSERT INTO @Table
 (
     QuoteID,
     PolicyNumber,
     ExpirationDate
 )
 VALUES
 (
     1, -- QuoteID - int
     'Pol1', -- PolicyNumber - varchar
     '2019-05-01' -- ExpirationDate - date
 ),
  (
     2, -- QuoteID - int
     'Pol1', -- PolicyNumber - varchar
     '2018-05-01' -- ExpirationDate - date
 )


 SELECT QuoteID, [@Table].ExpirationDate    ,[@Table].PolicyNumber
    ,CAST(FIRST_VALUE(ExpirationDate) OVER (PARTITION BY PolicyNumber ORDER BY QuoteID DESC) AS DATE) as FIRST_VALUE_ExpirationDate --Correct
    ,CAST(LAST_VALUE(ExpirationDate) OVER (PARTITION BY PolicyNumber ORDER BY QuoteID ) AS DATE) as LAST_VALUE_ExpirationDate --Gives Incorrect 
 FROM @Table 
 ORDER BY QuoteID

【问题讨论】:

发布与您的结果相对应的示例数据并解释其中的问题。 @Serdia 。 . .我一般使用first_value(),因为last_value() 有一些怪癖。 【参考方案1】:

LAST_VALUE 上的每个文档:

默认范围是“RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT 行”。

并且该范围内的 LAST_VALUE 始终是当前行

所以改成:

  DECLARE @Table TABLE ( QuoteID int, PolicyNumber varchar(5), ExpirationDate date)
 INSERT INTO @Table
 (
     QuoteID,
     PolicyNumber,
     ExpirationDate
 )
 VALUES
 (
     1, -- QuoteID - int
     'Pol1', -- PolicyNumber - varchar
     '2019-05-01' -- ExpirationDate - date
 ),
  (
     2, -- QuoteID - int
     'Pol1', -- PolicyNumber - varchar
     '2018-05-01' -- ExpirationDate - date
 )


 SELECT QuoteID, t.ExpirationDate    ,t.PolicyNumber
    ,FIRST_VALUE(ExpirationDate) 
       OVER (PARTITION BY PolicyNumber 
             ORDER BY QuoteID DESC)  as FIRST_VALUE_ExpirationDate 
    ,LAST_VALUE(ExpirationDate) 
       OVER (PARTITION BY PolicyNumber 
             ORDER BY QuoteID ASC
             RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
     )  as LAST_VALUE_ExpirationDate
 FROM @Table  t
 ORDER BY QuoteID

哪些输出:

QuoteID     ExpirationDate PolicyNumber FIRST_VALUE_ExpirationDate LAST_VALUE_ExpirationDate
----------- -------------- ------------ -------------------------- -------------------------
1           2019-05-01     Pol1         2018-05-01                 2018-05-01
2           2018-05-01     Pol1         2018-05-01                 2018-05-01

【讨论】:

【参考方案2】:

您的代码得到了正确的结果。

first_value 中的降序 order by 将 2018-05-01 保持在顶部,然后再将其选为第一个值。使用last_value,升序的order by 将2019-05-01 保持在底部,因此您的last_value 将其选为最后一个值。

【讨论】:

以上是关于LAST_VALUE() 究竟是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

Django 内容类型究竟是如何工作的?

泛型究竟是如何工作的?

这个 Promise 示例究竟是如何工作的?

bufferedReader() 在 Kotlin 中究竟是如何工作的?

Spring BeanPostProcessor 究竟是如何工作的?

document.cookie 究竟是如何工作的?