这是我的数据(请注意,这仅适用于一个实体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这是诀窍.我使用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.
我相信您正在寻求使用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)