3

我有一组带有时间戳的 user_id 的登录数据。

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

例如。

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

我只想看到以下记录

  • 用户 1 2012-03-07 14:24:30.000
  • 用户 1 2012-03-07 15:30:30.000
  • 用户 1 2012-03-08 09:20:30.000
  • 用户 1 2012-03-08 10:30:30.000
  • 用户2 2012-03-07 15:20:30.000

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

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

任何帮助深表感谢!!

4

1 回答 1

3

在 Sql Server 2005 或更新版本中,此 CTE 将返回 LoginAt 日期时间表,从已选择的 LoginAts 中删除不到一小时的时间。

;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 游乐场是这样的

更新

行号分别适用于每一代。从WITH common_table_expression 中提取 (Transact-SQL)提取:

CTE 递归部分中的分析和聚合函数应用于当前递归级别的集合,而不是应用于 CTE 的集合。像 ROW_NUMBER 这样的函数只对当前递归级别传递给它们的数据子集进行操作,而不是对传递给 CTE 递归部分的整个数据集进行操作。有关更多信息,请参阅 J. 在递归 CTE 中使用分析函数。

于 2012-04-05T23:39:34.920 回答