2011-03-03 52 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 
;