2009-12-07 65 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