Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get matching data using rownumber in SQL Server?

I am new to SQL Server and I don't know how to word this question. I have feeling this might be repeated. If you know it please flag it as duplicate. I will explain with data what I am trying to achieve

Table data - sometable

ID  TKID    Status    DateTimeStamp            RunMin
-----------------------------------------------------
215  6      Start   2009-10-29 09:48:14.243    NULL
261  6      Stop    2009-10-30 10:05:16.460    1457
356  6      Start   2009-11-03 14:11:05.097    NULL
357  6      Stop    2009-11-03 15:20:05.133    1526
358  6      Start   2009-11-03 16:14:45.863    NULL
574  19     Start   2009-11-12 13:12:11.827    NULL
575  19     Stop    2009-11-12 13:47:23.077    35
543 259     Start   2009-11-12 09:01:24.013    NULL 
620 259     Stop    2009-11-14 11:25:30.177    NULL 
623 259     Start   2009-11-14 16:47:32.913    NULL 
720 352     Start   2009-11-18 17:47:38.637    NULL 
730 352     Stop    2009-11-19 08:22:28.317    874  
773 352     Start   2009-11-20 10:00:11.320    NULL 
778 352     Stop    2009-11-20 11:51:59.853    985  
812 352     Start   2009-11-20 17:51:35.640    NULL 
813 352     Stop    2009-11-20 17:53:52.373    987  
822 352     Start   2009-11-23 08:13:23.030    NULL 
823 352     Stop    2009-11-23 08:17:33.063    991  
901 352     Start   2009-12-01 10:50:16.547    NULL 
910 352     Stop    2009-12-01 10:50:54.200    991  

Expected output:

ID  TKID    Status    DateTimeStamp            RunMin      
-----------------------------------------------------
358  6      Start   2009-11-03 16:14:45.863    NULL     
623 259     Start   2009-11-14 16:47:32.913    NULL 

So basically I want to get the record which has the start status but doesn't have the stop status.

Now What I tried ..

I tried to use the ROW_NUMBER function as below,

;with cte as 
(
    select 
       *,
       ROW_NUMBER() OVER (PARTITION BY tkid 
                          ORDER BY tkid, DateTimeStamp) AS rn
    from Prog_Timer
)
SELECT * 
FROM 
   (SELECT * 
    FROM cte
    WHERE TkID IN (SELECT TkID
                   FROM cte 
                   GROUP BY TkID
                   HAVING COUNT(*)% 2 = 1)
) as d

It gives me result as

And then try to get the tkid with the Odd count and for that tkid got the data.

ID  TKID    Status    DateTimeStamp            RunMin
-----------------------------------------------------
215  6      Start   2009-10-29 09:48:14.243    NULL
261  6      Stop    2009-10-30 10:05:16.460    1457
356  6      Start   2009-11-03 14:11:05.097    NULL
357  6      Stop    2009-11-03 15:20:05.133    1526
358  6      Start   2009-11-03 16:14:45.863    NULL
543 259     Start   2009-11-12 09:01:24.013    NULL 
620 259     Stop    2009-11-14 11:25:30.177    NULL 
623 259     Start   2009-11-14 16:47:32.913    NULL 

I don't know how to get the last row only from this output for each tkid select only the last start row. I think my approch is pretty complicated. There has to be simple way to get what I want. If you have new approach feel free to post. If you have anything to add to my existing query feel free to post. In case of confusion feel free to comment.

like image 917
user2745246 Avatar asked Feb 19 '26 03:02

user2745246


1 Answers

If you modify your ROW_NUMBER() PARTITION to order by DateTimeStamp desc, then the latest row for each tkid will be given rn=1, thus giving you the latest status for each tkid. You then simply have to SELECT rows where the rn = 1 and the Status = 'Start' to get your desired output:

select * from
(select 
   *,
   ROW_NUMBER() OVER (PARTITION BY tkid order by DateTimeStamp desc) as rn
from Prog_Timer
)
T
where 
T.rn = 1 -- the latest status for each tkid 
and T.Status = 'Start' -- returns only started and not stopped timers
-- if timer is stopped, t.Status will be 'Stop' in the latest row
like image 142
ASh Avatar answered Feb 20 '26 15:02

ASh