为什么LAST_VALUE()在SQL Server中不起作用?

RJ.*_*RJ. 5 sql sql-server

这是我的数据(请注意,这仅适用于一个实体ID /员工ID,将有多个.一个实体ID下可以有多个员工ID):

SELECT  EntityId,
        EmployeeId,
        PayPeriodStart,
        IsFullTime
FROM    dbo.Payroll
WHERE   EmployeeId = 316691
        AND PayPeriodStart <= '12/31/2014'
        AND PayPeriodEnd >= '1/1/2014';
Run Code Online (Sandbox Code Playgroud)

我想获取每个EntityID和EmployeeID组合的最后"IsFullTime"值.

我试过这样做:

SELECT  EntityId,
        EmployeeId,
        LAST_VALUE(IsFullTime) OVER (PARTITION BY EntityId, EmployeeId ORDER BY EntityId, EmployeeId, PayPeriodStart) AS LastIsFullTimeValue
FROM    dbo.Payroll
WHERE   EmployeeId = 316691
        AND PayPeriodStart <= '12/31/2014'
        AND PayPeriodEnd >= '1/1/2014';
Run Code Online (Sandbox Code Playgroud)

但是我得到了这个:

该查询应仅返回FOR EACH EntityID/EmployeeID的一行.

我究竟做错了什么?

sha*_*t00 13

尝试添加 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING

我相信分析函数的默认窗口包括ORDER BY当前行的结尾.

LAST_VALUE(IsFullTime) OVER (
    PARTITION BY EntityId, EmployeeId
    ORDER BY EntityId, EmployeeId, PayPeriodStart
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS LastIsFullTimeValue
Run Code Online (Sandbox Code Playgroud)


小智 6

要了解正在发生的情况,您必须了解框架的概念。该框架允许您为窗口指定一组甚至比分区更小的行。默认框架包含从第一行开始到当前行的行。对于第 1 行,窗口只是第 1 行。对于第 3 行,窗口包含第 1 行到第 3 行。使用 FIRST_VALUE 时,默认情况下包含第一行,因此您\xe2\x80\x99 不必担心它得到预期的结果。

\n\n

当将 LAST_VALUE 与默认框架一起使用时,窗口仅前进到当前行。当前行是窗口的最后一行。要解决此问题,您必须指定框架,在本例中为 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING。这意味着窗口从当前行开始,到分区的最后一行结束。运行下一个示例以了解如何正确使用 LAST_VALUE。

\n\n

查看http://www.sqlservercentral.com/articles/T-SQL/124112/

\n


Prz*_*min 5

这是诀窍.我使用FIRST_VALUE+ DESC排序(而不是LAST_VALUE+ ASC排序).作品.这是最短的方式,它可以让你避免畏惧 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.

FIRST_VALUE(IsFullTime) OVER (
    PARTITION BY EntityId, EmployeeId
    ORDER BY EntityId DESC, EmployeeId DESC, PayPeriodStart DESC
) AS LastIsFullTimeValue
Run Code Online (Sandbox Code Playgroud)

同意,令人困惑的LAST_VALUE是,为什么不直观,与其孪生姐妹相比需要如此多的关注FIRST_VALUE.

  • 谢谢,非常适合我!但我不明白为什么last_value不起作用 (2认同)

Fut*_*Fan 4

我相信您正在寻求使用ROW_NUMBER()并根据payperiodstart日期获取最后的值:

SELECT t.EntityId
    ,t.EmployeeId
    ,t.LastIsFullTimeValue
FROM (
    SELECT EntityId
        ,EmployeeId
        ,ROW_NUMBER() OVER (
            PARTITION BY EntityId
            ,EmployeeId ORDER BY PayPeriodStart DESC
            ) AS rn
        ,LastIsFullTimeValue
    FROM dbo.Payroll
    WHERE EmployeeId = 316691   -- you could probably put this in your outer query instead
        AND PayPeriodStart <= '12/31/2014'
        AND PayPeriodEnd >= '1/1/2014'
    ) t
WHERE t.rn = 1;
Run Code Online (Sandbox Code Playgroud)