2009-12-07 70 views
2

我想寫一個SQL Server查詢,但沒有運氣,並想知道如果任何人可能有任何想法如何實現我的查詢。SQL Server比較後續行重複

我想要做的事:

我有幾列命名是我處理的TaskID,的StatusCode,時間戳的那些表。現在這張表只保存了一天中運行的一個系統的任務,當它運行時它會得到一個時間戳和狀態碼,具體取決於該任務的狀態。

有時會發生什麼情況是任務表將被更新爲新的時間戳,但是自上次更新任務以來statusCode不會發生任何更改,因此對於給定任務的兩個或更多連續行,statusCode可以是相同的。當我說連續的行時,我的意思是時間戳。

因此,示例任務88可能在狀態碼2處具有20行,之後狀態碼更改爲其他內容。

現在我正試圖做的事情沒有運氣,現在是從這張表中檢索所有任務和狀態碼和時間戳列表,但在我有一個以上任務的連續行使用相同的狀態碼,我只想用最低的時間戳記取第一行,並忽略該行的其餘部分,直到該任務的狀態碼更改。

爲了簡化在這種情況下,你可以假設我有一個taskid,我正在過濾,所以我只是看着一個單一的任務。

有沒有人有任何想法,我怎麼能做到這一點,或者可能是我coudl可能讀了幫助我的東西?

謝謝 Irfan。

+0

我忘了提我正在使用SQL SERVER 2005 – Iffy 2009-12-07 17:42:15

+0

你試圖做的事聽起來對我來說非常程序化 - 所以也許你最好在C#這樣的事情上做這件事,而不是試圖彎曲T-SQL來做這件事。 – 2009-12-07 19:56:25

+0

嘿馬克,你知道我就是這麼想的,但是我試圖這樣做的原因是爲了減少來自SQL的負載。如果沒有這個邏輯來完成某些任務,由於重複的狀態碼行數量很大,我可以得到幾千行。如果我可以減少結果集根據狀態碼只包含不同的行,這將大大加快速度。 – Iffy 2009-12-07 22:27:41

回答

2

這是得到的一對夫婦的方式,你想要什麼:

SELECT 
    T1.task_id, 
    T1.status_code, 
    T1.status_timestamp 
FROM 
    My_Table T1 
LEFT OUTER JOIN My_Table T2 ON 
    T2.task_id = T1.task_id AND 
    T2.status_timestamp < T1.status_timestamp 
LEFT OUTER JOIN My_Table T3 ON 
    T3.task_id = T1.task_id AND 
    T3.status_timestamp < T1.status_timestamp AND 
    T3.status_timestamp > T2.status_timestamp 
WHERE 
    T3.task_id IS NULL AND 
    (T2.status_code IS NULL OR T2.status_code <> T1.status_code) 
ORDER BY 
    T1.status_timestamp 

SELECT 
    T1.task_id, 
    T1.status_code, 
    T1.status_timestamp 
FROM 
    My_Table T1 
LEFT OUTER JOIN My_Table T2 ON 
    T2.task_id = T1.task_id AND 
    T2.status_timestamp = (
      SELECT 
       MAX(status_timestamp) 
      FROM 
       My_Table T3 
      WHERE 
       T3.task_id = T1.task_id AND 
       T3.status_timestamp < T1.status_timestamp) 
WHERE 
    (T2.status_code IS NULL OR T2.status_code <> T1.status_code) 
ORDER BY 
    T1.status_timestamp 

兩種方法都依賴於有作爲status_timestamp值不完全匹配(兩行不能有一個給定的TASK_ID完全相同status_timestamp。)

+0

謝謝湯姆,我用了一些MODS的查詢來爲我的目的工作,但它做到了這一點,並且非常快。 非常感謝您的幫助。 – Iffy 2009-12-09 17:49:54

+0

不客氣! – 2009-12-09 18:10:50

1

喜歡的東西

select TaskID,StatusCode,Min(TimeStamp) 
from table 
group by TaskID,StatusCode 
order by 1,2 

注意,是的StatusCode可以複製,您將需要一個額外的領域,但希望這可以爲您指出正確的方向...

+0

感謝您的回覆Sparky。這真的很接近,但是這個問題在表中,我只想忽略任務的給定狀態的剩餘行,如果它的連續行跟隨着相同的狀態碼。例如。任務可以轉到狀態碼2,然後到3,然後返回到2,這些都是我想顯示的所有有效行,因爲狀態碼2沒有連續發生。我認爲你的查詢會給我這個任務給定狀態的最小時間戳。這就是爲什麼我的查詢很奇怪,因爲連續的行問題。 – Iffy 2009-12-07 17:49:04

0

類似於下面的東西應該得到你在正確的方向....

CREATE TABLE #T 
(
    TaskId INT 
    ,StatusCode INT 
    ,StatusTimeStamp DATETIME 
) 

INSERT INTO #T 
SELECT 1, 1, '2009-12-01 14:20' 
UNION SELECT 1, 2, '2009-12-01 16:20' 
UNION SELECT 1, 2, '2009-12-02 09:15' 
UNION SELECT 1, 2, '2009-12-02 12:15' 
UNION SELECT 1, 3, '2009-12-02 18:15' 

;WITH CTE AS 
(
SELECT TaskId 
     ,StatusCode 
     ,StatusTimeStamp 
     ,ROW_NUMBER() OVER (PARTITION BY TaskId, StatusCode ORDER BY TaskId, StatusTimeStamp DESC) AS RNUM 
FROM #T 
) 
SELECT TaskId 
     ,StatusCode 
     ,StatusTimeStamp 
FROM CTE 
WHERE RNUM = 1 

DROP TABLE #T 
+0

感謝周杰倫,這是一個非常聰明的查詢,但這又與Sparky上面的查詢具有相同的問題,它將statuscode和taskid分組在一起,並且只爲每個狀態碼返回一行。一個例子是,如果我要把行 UNION SELECT 1,2,'2009-12-02 19:15'; 到你的查詢中,這個狀態碼已經被插入,但是這個狀態碼不是連續的,所以應該顯示。上面的查詢將這一行與其他行進行分組。 – Iffy 2009-12-07 18:14:33

+0

我在想,也許我寫了一個遊標,在那裏我跟蹤了以前的狀態碼,如果它與當前的相同,我不會進入我的臨時表,否則,如果它不同,那麼我進入我的臨時表。在這個結尾,我將有一個臨時表與數據,我希望它與較慢的查詢由於光標。這一切都取決於光標需要多長時間才能完成這個操作,如果我去那個方向,coupld有一百行? – Iffy 2009-12-07 18:15:34