2012-04-05 41 views
3

我有一组具有时间戳的user_id的登录数据。如何在sql server中相隔一个小时挑选记录

用户可以多次登录,但我们需要从最少记录开始至少相隔一小时返回记录。该删除必须发生在用户级别(可以有多个用户)

例如,

  • USER1 2012-03-07 14:24:30.000
  • USER1 2012-03-07 14:34:30.000
  • USER1 2012-03-07 15:14:30.000
  • USER1 2012 -03-07 15:20:30.000
  • USER1 2012-03-07 15:30:30.000
  • USER1 2012-03-08 09:20:30.000
  • USER1 2012-03-08 9时50: 30.000
  • user1 2012-03- 08 10:30:30.000
  • 用户2 2012-03-07 15:20:30.000

我只希望看到以下记录

  • USER1 2012-03-07 14:24 :30.000
  • USER1 2012-03-07 15:30:30.000
  • USER1 2012-03-08 09:20:30.000
  • USER1 2012-03-08 10:30:30.000
  • USER2 2012-03-07 15:20:30.000

================================== ======================================

有没有办法做到这一点一个干净的方式?我们可以递归地做到这一点,但我希望有可能通过使用row_number分区。

任何帮助非常感谢!

+0

什么版本的sql server? – Glenn 2012-04-05 23:21:07

回答

3

在Sql Server 2005或更新版本中,此CTE将返回LoginAt日期时间表,将已经选择的LoginAts之外的时间除去小于1小时的表。

;with SkipHour(UserID, LoginAT, rn) as (
    select UserID, min(LoginAt), cast (1 as bigint) 
    from LogTable 
    group by UserID 
    union all 
    select SkipHour.UserID, LogTable.LoginAt, 
     row_number() over (partition by SkipHour.UserID 
          order by Logtable.LoginAt) rn 
    from SkipHour 
    inner join LogTable 
     on LogTable.UserID = SkipHour.UserID 
    where datediff(minute, SkipHour.LoginAt, LogTable.LoginAt) >= 60 
    -- Only first rows from previous generation qualify to have children 
     and rn = 1 
) 
select * 
from SkipHour 
where rn = 1 
order by UserID, LoginAT 

关键部分是row_number()。由于Sql Server不允许聚集函数和顶级谓词,因此row_number()是唯一的方法(IMO)来订购loginAt日期时间并仅保留第一个日期时间。

Sql Fiddle playground is this way

UPDATE

行数都是适用于每一代独立。从WITH common_table_expression (Transact-SQL)提取:

分析和聚合函数在CTE的递归部分被 施加到该组当前递归层次,而不是该组 为CTE。诸如ROW_NUMBER之类的函数仅对当前递归级别传递给它们的数据的子集 进行操作,而不是对CTE的递归部分递增的整个 数据集合进行操作。有关更多 信息,请参阅J.在递归CTE中使用分析函数。

+0

嘿尼古拉!谢谢一堆!这很好。你可以向我解释当基本记录的时间大于一小时时,重新开始编号的分区是如何的? 例如。 该cte获取每个用户的最小条目。然后我们根据大于cte记录的时间条目加入主表。然后它分配row_numbers。是什么让row_number重新启动一个特定的用户ID? 所以从cte的min入口是10.30上午 ,我们现在加入到上午11点31分,上午11点35分,上午11点40分(它分别获得行号1,2和3),但是对于12:10 PM,是什么让row_number开始回到1?) – user1316437 2012-04-06 15:44:05

+0

@ user1316437请看看我更新的答案。 – 2012-04-06 18:02:26

相关问题