当前位置: 首页 > 知识库问答 >
问题:

SQL服务器-在时间范围内选择频繁记录

李凯定
2023-03-14

我正在寻找一种方法来选择所有记录,其中一列具有相同的记录,并且日期时间彼此之间的间隔不超过5分钟。我管理一个票务系统,我试图查看5分钟内创建的所有类似票务。有关示例数据集,请参见以下内容:

|ID |Subject    |CreatedDateTime    |
-------------------------------------
|1  |A          |2020-09-28 11:01:00|
|2  |A          |2020-09-28 11:02:00|
|3  |A          |2020-09-28 11:03:00|
|4  |A          |2020-09-28 11:03:09|
|5  |A          |2020-09-28 11:04:52|
|6  |A          |2020-09-28 11:15:00|
|7  |B          |2020-09-28 11:20:00|
|8  |B          |2020-09-28 11:20:00|
|9  |B          |2020-09-28 11:20:00|

我的目标是只选择1-5条记录,因为5条记录是同一主题,它们都是在5分钟内创建的。不应选择6-10,因为受试者数量不够多,或者超出了规定的时间范围。

下面是我到目前为止的一个测试查询,但它没有考虑5分钟的范围(我只回顾了1周,因此是该条款):

SELECT Subject,COUNT(*)
FROM TableName
WHERE CreatedDateTime > DATEADD(day, -7, GETDATE())
GROUP BY Subject
HAVING COUNT(*) > 5 
ORDER BY COUNT(*) DESC;

有没有办法只在很短的时间内看到类似的记录?提前谢谢大家!

共有2个答案

谯翔
2023-03-14

如果您希望对彼此在5分钟内的记录进行分组,那么您可以使用递归查询对日期范围进行“分组”,如下所示

with data
  as (select *,row_number() over(partition by subject order by createddatetime) as rnk
        from t
        )
    ,cte
    as(select id,subject,createddatetime as begin_date, createddatetime,cast(1 as int) as grp
         from data
       where rnk=1  
       union all
       select b.id
             ,b.subject
             ,b.createddatetime
             ,case when datediff(minute,a.createddatetime,b.createddatetime) > 5 then 
                    b.createddatetime
                   else
                    a.createddatetime
               end as createddatetime
             ,case when datediff(minute,a.createddatetime,b.createddatetime) > 5 then 
                    a.grp+1
                   else
                    a.grp
               end as grp  
         from cte a
         join t b
           on a.id+1=b.id
          and a.subject=b.subject 
       )
     select * from cte  order by 1

 +----+---------+-------------------------+-------------------------+-----+
| id | subject |       begin_date        |     createddatetime     | grp |
+----+---------+-------------------------+-------------------------+-----+
|  1 | A       | 2020-09-28 11:01:00.000 | 2020-09-28 11:01:00.000 |   1 |
|  2 | A       | 2020-09-28 11:02:00.000 | 2020-09-28 11:01:00.000 |   1 |
|  3 | A       | 2020-09-28 11:03:00.000 | 2020-09-28 11:01:00.000 |   1 |
|  4 | A       | 2020-09-28 11:03:09.000 | 2020-09-28 11:01:00.000 |   1 |
|  5 | A       | 2020-09-28 11:04:52.000 | 2020-09-28 11:01:00.000 |   1 |
|  6 | A       | 2020-09-28 11:15:00.000 | 2020-09-28 11:15:00.000 |   2 |
|  6 | A       | 2020-09-28 11:17:00.000 | 2020-09-28 11:17:00.000 |   2 |
|  7 | B       | 2020-09-28 11:20:00.000 | 2020-09-28 11:20:00.000 |   1 |
|  8 | B       | 2020-09-28 11:20:00.000 | 2020-09-28 11:20:00.000 |   1 |
|  9 | B       | 2020-09-28 11:20:00.000 | 2020-09-28 11:20:00.000 |   1 |
+----+---------+-------------------------+-------------------------+-----+

DB小提琴链接

https://dbfiddle.uk/?rdbms=sqlserver_2019

百里诚
2023-03-14

您可以在每个记录前面和后面达到峰值,以分钟为单位查找时差,然后仅保留在5分钟内至少连接到另一条记录的记录:

WITH cte AS (
    SELECT *,
           DATEDIFF(minute,
               LAG(CreatedDateTime) OVER (PARTITION BY Subject
                                          ORDER BY CreatedDateTime),
               CreatedDateTime) AS LagCreatedDateTime,
           DATEDIFF(minute,
               CreatedDateTime,
               LEAD(CreatedDateTime) OVER (PARTITION BY Subject
                                           ORDER BY CreatedDateTime))
                AS LeadCreatedDateTime
    FROM TableName
)

SELECT *
FROM cte
WHERE LagCreatedDateTime <= 5 OR LeadCreatedDateTime <= 5;

请参阅下面的演示链接,以获取使用示例数据运行的示例。

 类似资料:
  • 问题内容: 我有一个存储表,,,,如: 现在,如果我有IP地址,如何检索匹配记录? 编辑 根据戈登的答案(我遇到编译错误),这就是我的想法: 但这给了我一个错误: 有任何想法吗? 问题答案: 痛苦的。SQL Server具有糟糕的字符串操作功能。但是,它提供了。此方法将IP地址转换为较大的十进制值以进行比较: 我应该注意,IP地址通常以4字节无符号整数的形式存储在数据库中。这使比较容易得多。。。尽

  • 范围选择器(rangeSelector)是图表中用于选择数据范围的工具,它提供了预配置的时间选择按钮,包括 1天,1周,1个月等,同时也提供时间输入框用于手动指定时间范围。 时间选择按钮 通过 rangeSelector.buttons 可以指定时间选择按钮,默认是 buttons: [{ type: 'month', count: 1, text: '1m' }, {

  • 问题内容: T-SQL DateTime问题。 我有一组时间范围。在这些时间范围内,可能会有一组重叠的时间范围,我称之为“封锁”时间。封锁的时间不会超过一天。我想要做的是分配时间以排除阻塞时间,基本上是给我没有“阻塞”的时间范围。可以肯定的是,阻塞时间不能超出时间范围。 示例:我工作时间是从上午9点到下午5点,在下午1点有30分钟的午餐时间。我想要2行的结果:9am至1pm和1.30pm至5pm。

  • 问题内容: 如何在MySQL中的日期范围之间选择数据。我的专栏是24小时的祖鲁时间格式。 尽管在这些时间段之间有数据,但不返回任何内容。我是否必须强制 “发件人” 和 “发件人” 字段中的值键入查询? 问题答案: 您需要更新日期格式:

  • 我的数据库中有100000个地址(即记录)。 它们中的每一个都有自己的坐标(纬度和经度)。 现在,考虑到用户的地理位置(纬度和经度),我只想在地图上显示5英里范围内的地址(使用Google maps v3 API)。 这意味着通常在100000个地址中只需显示5或6个地址。 一种解决方案可能是检索所有记录,并在Java中应用一个公式来计算每个地址的距离,并且仅当它在范围内时才显示它。 这将浪费处理

  • 在包含所有数据的生产性系统上。 是否有一个(最好是cql)查询可以与给定的列族或de一起平稳运行,我们必须更改设计?