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

时间:2015-08-07 18:35:45

标签: 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';

我想获取每个EntityID&amp;的最后“IsFullTime”值。 EmployeeID组合。

我试过这样做:

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';

但我得到了这个:

查询应该只返回一行FOR EACH EntityID / EmployeeID。

我做错了什么?

4 个答案:

答案 0 :(得分:12)

尝试添加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

答案 1 :(得分: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

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

答案 2 :(得分:2)

我相信您希望使用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;

答案 3 :(得分:0)

要查看正在发生的情况,您必须了解框架的概念。该框架允许您为窗口指定一组行,该行甚至比分区小。默认框架包含从第一行到当前行的所有行。对于第1行,该窗口仅是第1行。对于第3行,该窗口包含第1至3行。使用FIRST_VALUE时,默认情况下包括第一行,因此您不必担心会获得预期的结果

将LAST_VALUE与默认框架一起使用时,该窗口仅上升到当前行。当前行是窗口的最后一行。要变通解决此问题,您必须指定框架,在这种情况下行在当前行和未绑定跟随之间行。这意味着窗口从当前行开始,并在分区的最后一行结束。运行下一个示例,看看如何正确使用LAST_VALUE。

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