2009-08-06 79 views
2

下面的列表的情況是:SQL服務器 - 選擇最新記錄產生變化

我的「票」一個數據庫,我們跟蹤每個它們保存時間更改門票。我專門找在狀態發生變化,這與以下格式跟蹤:

狀態:{FROM}:{TO}

與{FROM}和{TO}更改爲相應的狀態。我需要做的是在任何給定的一週結束時,例如在過去的12周內,按照「開放」(意味着處於草稿狀態)的票數週數來生成數字。但是,您並不僅限於「關閉」票證,然後重新打開它,或者在一週內進行多次更改。

所以,我需要做的是修改下面的SQL,只考慮任何給定條目的最新「動作」。這樣我們就避免了由於已經打開計數而出現「已關閉」的條目,因爲它們已經提前打開。

SELECT track.historyID 
     FROM RS_HistoryTracker track 
    WHERE (track.action = 'STATUS:INITIAL:DRAFT' 
      OR track.action = 'STATUS:DELETED:DRAFT' 
      OR track.action = 'STATUS:DRAFT:DRAFT') 
     AND track.trackDateTime <= @endOfWeek 

不過,這一說法被包含在另一個SELECT語句中,並且被用來產生的歷史項目的完整列表:

SELECT COUNT(DISTINCT his.historyID) AS theCount 
    FROM RS_History his 
WHERE his.historyID IN 
     (SELECT track.historyID 
      FROM RS_HistoryTracker track 
     WHERE (track.action = 'STATUS:INITIAL:DRAFT' 
       OR track.action = 'STATUS:DELETED:DRAFT' 
       OR track.action = 'STATUS:DRAFT:DRAFT') 
      AND track.trackDateTime <= @endOfWeek) 

那麼,如何使只有內部的選擇考慮到最近追蹤到達或在endOfWeek日期的'行動'? HistoryTracker包含日期時間戳記列。

+0

我認爲你在表軌中有一個票證ID字段。所以基本上你想加入一個結果集,其中包含每個票據ID的最大歷史記錄ID。 – pjp 2009-08-06 15:41:00

+0

是的,我們確實跟蹤軌道表中的車票ID – Ipster 2009-08-06 15:44:03

+0

至於最大歷史ID,情況可能並非如此。如果我在3個月前運行一個星期的查詢,則需要最新的歷史記錄,直至包括該周的結束日期,而忽略該周後發生的所有歷史記錄。 – Ipster 2009-08-06 15:46:46

回答

0

看起來是這樣工作的:

SELECT query.historyID 
    FROM 
    (SELECT MAX(track.trackID) AS maxTrackID, track.historyID 
    FROM RS_HistoryTracker track 
    WHERE track.trackDateTime <= '2009-08-06 23:59:59' 
     AND track.action LIKE 'STATUS:%' 
    GROUP BY historyID) AS query, RS_HistoryTracker track 
    WHERE track.historyID = query.historyID 
     AND track.trackID = query.maxTrackID 
     AND track.action LIKE 'STATUS:%:DRAFT' 
+0

感謝所有的建議 - 我採取了各自的部分和整合到這一點。 – Ipster 2009-08-06 16:27:37

+0

儘管LIKE運算符可以爲您提供縮短代碼的捷徑,嚴重的是,如果你能避免它,不要使用它。原因是它阻止了優化器使用索引,通常會導致性能下降。 – MatBailie 2009-08-07 09:05:43

+1

另外,使用日期範圍時只是一般性評論,最好使用「> = @start」和「<@end」。所以如果你想在8月6日結束之前把所有的東西都重新設定,那麼在8月7日之前就應該把它改寫成所有的東西。原因在於無論您使用何種數據類型,邏輯都適用。在你的「<= @end」示例中,如果時間戳是23:59:59之後的幾毫秒,那該怎麼辦?如果TrackDateTime是SmallDateTime,則只需使用23:59而不用秒。使用「<@end」可以消除所有這些考慮因素,以及其他查詢中的更多內容。 – MatBailie 2009-08-07 09:10:35

1

擔任首發,你可以做這樣的事情

select * from 
(
    --find max history id for each ticket 
    select 
     T1.ticketId, 
     max(T1.historyId) As LastHistoryId 
    from #Ticket T1 
    --add WHERE clause to filter out dates 
    group by 
     T1.ticketId 
) MaxTicket 

inner join 
#Ticket T2 --find the ticket so you can get the status 
on MaxTicket.ticketId = T2.ticketId 
and MaxTicket.LastHistoryId=T2.Historyid 

您可能希望找到每張門票的最後一個歷史記錄項改變你如何找到最新的門票是基於日期,而不是歷史ID。

+0

添加了'LIKE'子句以過濾掉不涉及狀態的更新。在日期工作。感謝您的建議 – Ipster 2009-08-06 15:58:56

+0

historid是一個外鍵 - 在執行聚合函數時沒有任何價值,它們將永遠是一樣的。 – 2009-08-06 16:06:13

1

的是這個問題的漂浮計算器上的很多變化,這裏是我第一次發現:)

sql-query-to-get-most-recent-row-for-each-instance-of-a-given-key

基本上你需要做兩個部分。
- 使用一個查詢發現每件
最近的時間戳 - 使用另一個查詢到你所要做

找到的所有項目仍然由給定日期開放工作:

SELECT 
    [data].* 
FROM 
    track AS [data] 
WHERE 
    [data].trackDateTime = 
    (
     SELECT 
      MAX(trackDateTime) 
     FROM 
      track 
     WHERE 
      track.ticketID = [data].ticketID 
      AND track.DateTime < @endOfWeek 
    ) 
    AND track.action IN ('STATUS:INITIAL:DRAFT','STATUS:DELETED:DRAFT','STATUS:DRAFT:DRAFT')) 

這假定ticketID是每張票的唯一標識符。 (根據您的意見之一)

1

將與SQL Server 2005+工作:

WITH history AS (
    SELECT rh.historyID, 
     MAX(rh.action) 'action' 
    FROM RS_HISTORYTRACKER rh 
    WHERE rh.action IN ('STATUS:INITIAL:DRAFT', 'STATUS:DELETED:DRAFT', 'STATUS:DRAFT:DRAFT') 
    AND rh.trackDateTime <= @endOfWeek) 
SELECT COUNT(DISTINCT t.historyID) AS theCount 
    FROM RS_HISTORY t 
    JOIN history h ON h.historyi = t.historyid 

備用,非CTE使用查詢:

SELECT COUNT(DISTINCT t.historyID) AS theCount 
    FROM RS_HISTORY t 
    JOIN (SELECT rh.historyID, 
       MAX(rh.action) 'action' 
      FROM RS_HISTORYTRACKER rh 
     WHERE rh.action IN ('STATUS:INITIAL:DRAFT', 'STATUS:DELETED:DRAFT', 'STATUS:DRAFT:DRAFT') 
      AND rh.trackDateTime <= @endOfWeek) h ON h.historyi = t.historyid 
+0

我仍然有這樣的問題,如果最近的狀態更改是STATUS:%:FINAL,它不會包含它,但似乎沒有發現。這是一個好的開始,並讓我思考。 – Ipster 2009-08-06 16:13:38

+0

如果IN子句只獲取INITIAL,它如何才能包含FINAL:DRAFT,DELETED:DRAFT或DRAFT:DRAFT?或者最後是RS_HISTORY表中的列/屬性? – 2009-08-06 16:30:52

+0

對不起,你是對的。我在窗口看着錯誤的代碼。 – Ipster 2009-08-06 17:39:32