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.
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
Lot of ways to do this, one of them is below:
SELECT T.*
FROM SOMETABLE T
JOIN (SELECT MAX(DATETIMESTAMP) MAXTIME, TKID
FROM SOMETABLE
GROUP BY TKID) SRC
ON SRC.MAXTIME = T.DATETIMESTAMP AND SRC.TKID = T.TKID
WHERE T.STATUS = 'Start'
Depending on the actual data, you might want to get MAX(ID) instead, in case it's sometimes possible for a process to stop and start at the same time. But of course, in case of updates it could be possible for older ID values to have newer timestamps.
I think this can show your results:
select *
from Prog_Timer st
where st.[Status] = 'Start' And
isnull((select min(sti.DateTimeStamp) from Prog_Timer sti
where sti.[Status] = 'Stop' And sti.TKId = st.TKId And sti.DateTimeStamp > st.DateTimeStamp )
, cast('2999/12/29' as datetime))
>
isnull((select min(stii.LogDateTime) from Prog_Timer stii
where stii.[Status] = 'Start' And stii.TKId = st.TKId And stii.DateTimeStamp > st.DateTimeStamp)
, cast('2999/12/29' as datetime))
But I'm waiting for best answer ;).
how about this:
;with cte as
(
select *
, MAX(DateTimeStamp) OVER (PARTITION BY tkid) AS maxDt
from Prog_Timer
)
SELECT *
FROM cte
WHERE DateTimeStamp=maxDt and Status='Start'
Try this query:
SELECT *
FROM tableName
WHERE Status = 'start'
AND ID NOT IN (SELECT ID
FROM tableName
WHERE Status = 'stop')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.