[英]How to get matching data using rownumber in SQL Server?
我是SQL Server的新手,我不知道怎么说这个问题。 我觉得这可能会重演。 如果您知道,请将其标记为重复。 我将用数据解释我想要实现的目标
表数据- 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
预期产量:
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
所以基本上我想获得具有start
状态但没有stop
状态的记录。
现在我尝试了什么..
我尝试使用ROW_NUMBER
函数,如下所示,
;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
它给了我结果
然后尝试使用Odd
计数得到tkid,并且tkid得到了数据。
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
我不知道如何从每个tkid
这个输出中获取最后一行只选择最后一个开始行。 我认为我的approch非常复杂。 必须有简单的方法来获得我想要的东西。 如果您有新方法,请随时发布。 如果您有任何要添加到我现有查询的内容,请随时发布。 如果有困惑,请随意评论。
如果您order by DateTimeStamp desc
修改ROW_NUMBER() PARTITION
以进行order by DateTimeStamp desc
,那么每个tkid
的最新行将被赋予rn=1
,从而为您提供每个tkid
的最新状态。 然后你只需要SELECT
rn = 1
和Status = 'Start'
来获得你想要的输出:
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
有很多方法可以做到这一点,其中之一是:
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'
根据实际数据,您可能希望获得MAX(ID),以防有时进程可以停止并同时启动。 但是,当然,在更新的情况下,旧ID值可能具有更新的时间戳。
我想这可以显示你的结果:
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))
但我在等待最好的答案;)。
这个怎么样:
;with cte as
(
select *
, MAX(DateTimeStamp) OVER (PARTITION BY tkid) AS maxDt
from Prog_Timer
)
SELECT *
FROM cte
WHERE DateTimeStamp=maxDt and Status='Start'
试试这个查询:
SELECT *
FROM tableName
WHERE Status = 'start'
AND ID NOT IN (SELECT ID
FROM tableName
WHERE Status = 'stop')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.