【问题标题】:Find duplicate data in last 1 hour查找过去 1 小时内的重复数据
【发布时间】:2022-01-28 08:29:40
【问题描述】:

我正在寻找一个 SQL 脚本来查找过去 1 小时内有超过 2 个条目的数据。 我有一张包含 user_id 和 event_time 的表。我想要一种方法来确定 user_id 在过去 1 小时内是否有超过 1 个条目。

到目前为止我已经尝试过:

  1. 创建临时表以放置所有重复条目:
SELECT a.*
INTO #temp 
FROM Table a
JOIN (
    SELECT USERID, COUNT(*) AS Duplicates
    FROM Table
    GROUP BY userid
    HAVING count(*) > 1
) AS b ON a.userid = b.USERID
  1. 运行 self Joins 以获取时差小于等于 1 小时的记录:
SELECT a.*
FROM #temp a
INNER JOIN #temp b ON a.userid = b.USERID
WHERE DATEDIFF(hour, a.EVENTTIME, b.EVENTTIME) = 1

运行第一个脚本后,它会提供大约 800 多行重复数据。但是在运行第二个脚本后,我得到的数据是数千。 有人可以帮忙吗?

【问题讨论】:

  • 第一个脚本给出所有重复项 (800+) 第二个脚本将其限制为多个条目在一小时内的那些
  • 请提供一些样本数据和预期结果
  • 我们需要一个minimal reproducible example,其中包含示例数据、所需结果、实际结果和您的查询。
  • 所以基本要求是这样的:假设我有一个用户 ID,它全天都有多个 event_time 条目。我只想过滤掉事件时间差小于 1 小时的条目。
  • @Rathore 如果你有事件持续一整天,并且所有相邻事件之间的时间差小于一小时,你应该在这种情况下将它们全部删除吗?

标签: sql sql-server database tsql


【解决方案1】:

cross apply 可用于根据您的条件获取每个事件的所有相关事件,如下所示:

With CTE As (
Select USERID, EVENTTIME, Row_Number() Over (Order by USERID, EVENTTIME) As ID
From Tbl
)
Select a.ID, a.USERID, a.EVENTTIME, T.ID, T.USERID, T.EVENTTIME
From CTE As a Cross Apply (Select ID, USERID, EVENTTIME 
                           From CTE 
                           Where Abs(datediff(minute, a.EVENTTIME, EVENTTIME))<=60
                                 And USERID=a.USERID And ID<>a.ID) As T
Order by a.ID, a.USERID, a.EVENTTIME, T.ID, T.USERID, T.EVENTTIME

或者您可以在不绑定特定事件的情况下获取事件列表:

With CTE As (
Select USERID, EVENTTIME, Row_Number() Over (Order by USERID, EVENTTIME) As ID
From Tbl
)
Select T.USERID, T.EVENTTIME
From CTE As a Cross Apply (Select USERID, EVENTTIME 
                           From CTE 
                           Where Abs(datediff(minute, a.EVENTTIME, EVENTTIME))<=60
                                 And USERID=a.USERID And ID<>a.ID) As T
Group by T.USERID, T.EVENTTIME

db<>fiddle

要仅获取最后一小时的事件,您可以在CTEWhere 子句中添加适当的过滤器。

With CTE As (
Select USERID, EVENTTIME, Row_Number() Over (Order by USERID, EVENTTIME) As ID
From Tbl
Where EVENTTIME Between dateadd(minute, -60, GetDate()) And GetDate()
)
Select T.USERID, T.EVENTTIME
From CTE As a Cross Apply (Select USERID, EVENTTIME 
                           From CTE 
                           Where Abs(datediff(minute, a.EVENTTIME, EVENTTIME))<=60
                                 And USERID=a.USERID 
                                 And ID<>a.ID) As T
Group by T.USERID, T.EVENTTIME

【讨论】:

  • 非常感谢,第一个查询就是我要找的。祝你有美好的一天!!!
  • @Rathore 不客气!
【解决方案2】:

按日期差的小时数顺序为每组user_id 指定一个行号。请记住过滤过去 1 小时内具有 event_date 的行。

查询

;with cte as(
    select [rn] = row_number() over(
        partition by [user_id]
        order by [user_id], datediff(hour, [event_time], getdate())
    ), *
    from [your_table_name]
    where datediff(hour, [event_time], getdate()) < 2
)
select * from [your_table_name] as [t1]
where exists(
    select 1 from cte as [t2]
    where [t1].[user_id]= [t2].[user_id]
    and [t2].[rn] > 1
);

【讨论】:

  • 非常感谢!!!我会尝试测试一下。
猜你喜欢
  • 2010-10-07
  • 2011-12-26
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
相关资源
最近更新 更多