Sql 如果值为-1,则返回上一条记录中的值

Sql 如果值为-1,则返回上一条记录中的值,sql,sql-server,tsql,sql-server-2008,null,Sql,Sql Server,Tsql,Sql Server 2008,Null,我有一个包含LocationId字段的表。在某些情况下,如果记录共享相同的外键,LocationId可能会作为-1出现 我想做的是在我的select查询中,在发生这种情况时,是前面的位置 示例数据: Record FK StartTime EndTime Location 1 110 2011/01/01 12.30 2011/01/01 6.10 456 2 110 2011/01/01

我有一个包含LocationId字段的表。在某些情况下,如果记录共享相同的外键,LocationId可能会作为-1出现

我想做的是在我的select查询中,在发生这种情况时,是前面的位置

示例数据:

Record  FK     StartTime               EndTime          Location
1       110  2011/01/01 12.30        2011/01/01 6.10      456
2       110  2011/01/01 3.40         2011/01/01 4.00       -1
3       110  2011/01/02 1.00         2011/01/02 8.00      891
4       110  2011/01/02 5.00         2011/01/02 6.00       -1
5       110  2011/01/02 6.10         2011/01/02 6.30       -1

对于记录2,-1应该是456,对于记录4和记录5,-1应该是891,对于整个结果集

with tmp(Record ,FK ,StartTime ,EndTime ,Location)
as( select
1, 110 ,'2011/01/01 12:30', '2011/01/01 6:10', 456 union all select
2, 110 ,'2011/01/01 3:40', '2011/01/01 4:00', -1 union all select
3, 110 ,'2011/01/02 1:00', '2011/01/02 8:00', 891 union all select
4, 110 ,'2011/01/02 5:00', '2011/01/02 6:00', -1 union all select
5, 110 ,'2011/01/02 6:10', '2011/01/02 6:30', -1
)

-- ignore above this line
select curr.Record, curr.FK, curr.StartTime, curr.EndTime,
 case when curr.Location=-1 then prev.Location else curr.Location end Location
from tmp curr
outer apply 
 (select top 1 prev.location
 from tmp prev
 where curr.location=-1 and prev.FK=curr.FK
 and prev.starttime < curr.starttime
 and prev.location <> -1
 order by prev.starttime desc) prev

对于整个结果集

with tmp(Record ,FK ,StartTime ,EndTime ,Location)
as( select
1, 110 ,'2011/01/01 12:30', '2011/01/01 6:10', 456 union all select
2, 110 ,'2011/01/01 3:40', '2011/01/01 4:00', -1 union all select
3, 110 ,'2011/01/02 1:00', '2011/01/02 8:00', 891 union all select
4, 110 ,'2011/01/02 5:00', '2011/01/02 6:00', -1 union all select
5, 110 ,'2011/01/02 6:10', '2011/01/02 6:30', -1
)

-- ignore above this line
select curr.Record, curr.FK, curr.StartTime, curr.EndTime,
 case when curr.Location=-1 then prev.Location else curr.Location end Location
from tmp curr
outer apply 
 (select top 1 prev.location
 from tmp prev
 where curr.location=-1 and prev.FK=curr.FK
 and prev.starttime < curr.starttime
 and prev.location <> -1
 order by prev.starttime desc) prev

可以使用相关子查询。例如:

SELECT *
    , (SELECT TOP 1 Location
       FROM MyTable T2
       WHERE T2.Record <= T1.Record
       AND T2.FK = T1.FK
       AND T2.Location <> -1
       ORDER BY T2.Record DESC) AS BestLocation
FROM MyTable T1

可以使用相关子查询。例如:

SELECT *
    , (SELECT TOP 1 Location
       FROM MyTable T2
       WHERE T2.Record <= T1.Record
       AND T2.FK = T1.FK
       AND T2.Location <> -1
       ORDER BY T2.Record DESC) AS BestLocation
FROM MyTable T1

不,你太离题了。。该表有超过800k条记录。。所以它需要健壮,并且不需要where语句中的FK值。@Matt我选择了starttime。如果你需要重新制作一个符咒的顺序,你可以交换记录。。谢谢你,RichardNo,你太离谱了。。该表有超过800k条记录。。所以它需要健壮,并且不需要where语句中的FK值。@Matt我选择了starttime。如果你需要重新制作一个符咒的顺序,你可以交换记录。。谢谢Richard,你能在子查询中使用ORDER BY吗?是的,当使用TOP N时,你可以在子查询中使用ORDER BY。但是,正如mattd所指出的,使用MAX而不是ORDER BY会更快。@ThomasMcLeod我是指你在回答中使用MAX的方式。排序方式意味着需要对结果进行排序,但使用MAX避免了排序,而代价是另一次表扫描。根据表的大小和可用的索引,表扫描可能会更快。您能在子查询中使用ORDER BY吗?是的,当使用TOP N时,您可以在子查询中使用ORDER BY。但是,正如mattd所指出的,使用MAX而不是ORDER BY会更快。@Thomasmclod我指的是您在回答中使用MAX的方式。排序方式意味着需要对结果进行排序,但使用MAX避免了排序,而代价是另一次表扫描。根据表的大小和可用索引,表扫描可能会更快。