我有一组带有时间戳的 user_id 登录数据。
用户可以多次登录,但我们需要从最短记录开始返回至少相隔一小时的记录。重复数据删除必须在用户级别进行(可以有多个用户)
for eg.
- 用户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 分区依据。
任何帮助深表感谢!!
在 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() 是对 loginAt 日期时间进行排序并仅保留第一个日期时间的唯一方法(IMO)。
Sql Fiddle 游乐场是这样的 http://sqlfiddle.com/#!3/db937/4.
UPDATE:
行号分别适用于每一代。摘自WITH common_table_expression (Transact-SQL) http://msdn.microsoft.com/en-us/library/ms175972%28v=sql.105%29.aspx:
CTE 递归部分中的分析函数和聚合函数是
应用于当前递归级别的集合而不是集合
对于 CTE。像 ROW_NUMBER 这样的函数仅对以下子集进行操作
由当前递归级别而不是整个递归级别传递给它们的数据
传递到 CTE 递归部分的数据集。了解更多
有关信息,请参阅 J. 在递归 CTE 中使用分析函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)