2011-03-03 82 views
0

我有一个包含LocationId字段的表。在某些情况下,如果记录共享相同的外键,则LocationId可能会以-1表示。如果值为-1,则返回以前记录的值

我想要做的是在我的选择查询是在这种情况下发生,以前的位置。

实施例的数据:

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 

-1应该出来作为456为记录2,和891用于记录4和5

+0

SQL Server 2005+? – RichardTheKiwi 2011-03-03 01:11:35

+0

SQL Server 2008 – Matt 2011-03-03 01:15:29

回答

2

对于整个结果集

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 
+0

不,你走的标记..该表有超过800K记录..所以它需要是健壮的,并不需要FK值在where语句.. – Matt 2011-03-03 01:13:07

+0

@Matt我选择沿着'starttime'。你可以交换'记录',如果这是你需要的订单 – RichardTheKiwi 2011-03-03 01:19:32

+0

工作魅力..感谢您的理查德 – Matt 2011-03-03 02:18:00

1

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

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 
+0

你可以在子查询中使用ORDER BY? – ThomasMcLeod 2011-03-03 02:21:16

+0

是的,您可以在使用'TOP N'时在子查询中使用'ORDER BY'。但是,正如mattd指出的那样,使用'MAX'而不是'ORDER BY'会更快。 – srgerg 2011-03-03 02:24:58

+0

MAX()'语法是如何工作的? – ThomasMcLeod 2011-03-07 17:45:01

1
SELECT 
    Record, 
    FK, 
    StartTime, 
    EndTime, 
(
    SELECT 
     Location 
    FROM 
     MyTable 
    WHERE 
     Record = 
    ( 
     SELECT 
      MAX(Record) 
     FROM 
      MyTable t2 
     WHERE 
      t2.Record =< t1.Record AND 
      Location >= 0 
    ) 
) 

FROM 
    MyTable t1 
2

此版本只招一个查找的成本,如果当前行中的位置值是-1。在查询计划中,如果位置<> -1,则左连接包含一个传递谓词,该谓词跳过运行连接的内侧。

; 
WITH CTE 
AS  (
     SELECT * 
     FROM (
       VALUES 
       (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', 89), 
       (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) 
       ) V (record, fk, start_time, end_time, location) 
     ) 
SELECT T1.record, 
     T1.fk, 
     T1.start_time, 
     T1.end_time, 
     CASE WHEN T1.location != -1 THEN Location 
     ELSE 
      (
      SELECT TOP (1) 
        T2.location 
      FROM CTE AS T2 
      WHERE T2.record < T1.record 
      AND  T2.fk = T1.fk 
      AND  T2.location != -1 
      ORDER BY T2.Record DESC 
      ) 
     END 
FROM CTE AS T1 
; 
相关问题