查找忽略重叠的总分钟数(将基于光标的答案转换为 CTE)

2023-12-05

有一个现有问题该问题询问如何查找多个日期范围内有多少分钟,忽略重叠。

给出的示例数据是(userID 不是特别相关)

--Available--
ID  userID  availStart          availEnd
1   456     '2012-11-19 16:00'  '2012-11-19 17:00'
2   456     '2012-11-19 16:00'  '2012-11-19 16:50'
3   456     '2012-11-19 18:00'  '2012-11-19 18:30'
4   456     '2012-11-19 17:30'  '2012-11-19 18:10'
5   456     '2012-11-19 16:00'  '2012-11-19 17:10'
6   456     '2012-11-19 16:00'  '2012-11-19 16:50'

我可以使用游标解决问题,但我认为它应该适用于 CTE,但我不知道该怎么做。

方法是按开始时间排列每个范围,然后我们构建一个范围,按顺序合并范围,直到找到一个不与我们合并范围重叠的范围。然后我们计算合并范围内有多少分钟,并记住这一点我们继续下一个范围,再次合并任何重叠的部分。每次获得不重叠的起点时,我们都会累积分钟数最后,我们将累积的分钟数添加到最后一个范围的长度上

很容易看出,由于顺序的原因,一旦某个范围与之前的范围不同,那么其他范围就不能与之前的范围重叠,因为它们的开始日期都更大。

Declare
  @UserID int = 456,
  @CurStart datetime, -- our current coalesced range start
  @CurEnd datetime, -- our current coalesced range end
  @AvailStart datetime, -- start or range for our next row of data
  @AvailEnd datetime, -- end of range for our next row of data
  @AccumMinutes int = 0 -- how many minutes so far accumulated by distinct ranges

Declare MinCursor Cursor Fast_Forward For
Select
  AvailStart, AvailEnd
From
  dbo.Available
Where
  UserID = @UserID
Order By
  AvailStart

Open MinCursor

Fetch Next From MinCursor Into @AvailStart, @AvailEnd
Set @CurStart = @AvailStart
Set @CurEnd = @AvailEnd

While @@Fetch_Status = 0
Begin
  If @AvailStart <= @CurEnd -- Ranges Overlap, so coalesce and continue
    Begin
    If @AvailEnd > @CurEnd 
      Set @CurEnd = @AvailEnd
    End
  Else -- Distinct range, coalesce minutes from previous range
  Begin
    Set @AccumMinutes = @AccumMinutes + DateDiff(Minute, @CurStart, @CurEnd)
    Set @CurStart = @AvailStart -- Start coalescing a new range
    Set @CurEnd = @AvailEnd
  End
  Fetch Next From MinCursor Into @AvailStart, @AvailEnd
End

Select @AccumMinutes + DateDiff(Minute, @CurStart, @CurEnd) As TotalMinutes

Close MinCursor
Deallocate MinCursor;

让 CTE 正常工作,只是递归中的一个愚蠢错误。查询计划的爆炸式增长令人印象深刻:

With OrderedRanges as (
  Select
    Row_Number() Over (Partition By UserID Order By AvailStart) AS RN,
    AvailStart,
    AvailEnd
  From
    dbo.Available
  Where
    UserID = 456
),
AccumulateMinutes (RN, Accum, CurStart, CurEnd) as (
  Select
    RN, 0, AvailStart, AvailEnd
  From
    OrderedRanges
  Where 
    RN = 1
  Union All
  Select
    o.RN, 
    a.Accum + Case When o.AvailStart <= a.CurEnd Then
        0
      Else 
        DateDiff(Minute, a.CurStart, a.CurEnd)
      End,
    Case When o.AvailStart <= a.CurEnd Then 
        a.CurStart
      Else
        o.AvailStart
      End,
    Case When o.AvailStart <= a.CurEnd Then
        Case When a.CurEnd > o.AvailEnd Then a.CurEnd Else o.AvailEnd End
      Else
        o.AvailEnd
      End
  From
    AccumulateMinutes a
        Inner Join 
    OrderedRanges o On 
        a.RN = o.RN - 1
)

Select Max(Accum + datediff(Minute, CurStart, CurEnd)) From AccumulateMinutes 

这是否适用于 CTE,是否有以这种方式累积列表的通用模式?

http://sqlfiddle.com/#!6/ac021/2


以下查询根据您的定义查找数据中的周期。它首先使用相关子查询来确定记录是否是一个时间段的开始(即与较早时间段没有重叠)。然后,它将“periodStart”指定为最近的开始,即非重叠周期的开始。

以下(未经测试的)查询采用这种方法:

with TimeWithOverlap as (
     select t.*,
            (case when exists (select * from dbo.Available tbefore where t.availStart > tbefore.availStart and tbefore.availEnd >= t.availStart)
                  then 0
                  else 1
             end) as IsPeriodStart
     from dbo.Available t 
    ),
    TimeWithPeriodStart as (
     select two.*,
            (select MAX(two1.AvailStart) from TimeWithOverlap two1 where IsPeriodStart = 1 and two1.AvailStart <= two.AvailStart
            ) as periodStart
     from TimeWithOverlap two
    )
select periodStart, MAX(AvailEnd) as periodEnd
from TimeWithPeriodStart twps
group by periodStart;

http://sqlfiddle.com/#!6/3483c/20(第二次查询)

如果两个周期同时开始,则它仍然有效,因为 AvailStart 值相同。由于存在相关子查询,即使在中等大小的数据集上,这也可能表现不佳。

还有其他方法可以解决这个问题。例如,如果您有 SQL Server 2012,您将能够使用累积和函数,它提供了一种更简单的方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查找忽略重叠的总分钟数(将基于光标的答案转换为 CTE) 的相关文章

  • 获取每件商品的最新价格

    我有一张桌子 ItemID PurchaseDate Price 001 03 17 2013 19 00 002 03 17 2013 14 00 001 03 18 2013 13 00 002 03 18 2013 15 00 001
  • 将记录与另一个表上的最新记录连接

    我正在尝试创建一个 SQL 视图 我如何从一个表中选择最新的记录 而其他记录保持原样 我需要从所有表中选择所有记录 这工作正常 但我需要仅按日期选择最新的提案 这是我遇到的问题 这是我到目前为止所拥有的 SELECT TOP 100 PER
  • 开发和生产 SQL Server 之间使用不同的排序规则会出现哪些问题?

    盘问 无法更新 sys columns 还有其他方法吗 https stackoverflow com questions 4018347 unable to update sys columns any other approach含糊地
  • 查看tomcat服务器的连接数

    我在 Tomcat Server 5 5 17 上部署了一个 Java Java EE Web 应用程序 我想知道连接到服务器的客户端数量 我们怎样才能找到它呢 最可靠的方法是搜索ip addr of srv port in netstat
  • 有向图 SQL

    我有以下数据集 它表示有向图中的节点 CREATE TABLE nodes NODE FROM VARCHAR2 10 NODE TO VARCHAR2 10 INSERT INTO nodes VALUES GT TG INSERT IN
  • PDO 和 Microsoft SQL:必须声明表变量“@P1”

    我正在尝试使用 PDO 中的绑定从 Microsoft SQL 数据库中选择一些条目 我正在使用的代码看起来与我在文档中找到的代码类似 但是 当我运行它时 我收到以下警告 警告 PDOStatement execute pdostateme
  • MySQL 命令输出在命令行客户端中太宽[重复]

    这个问题在这里已经有答案了 我在用mysql终端模拟器中的命令行客户端lxterminal在Ubuntu中 当我运行以下命令时 mysql gt select from routines where routine name simplep
  • SQL Server 数据归档解决方案

    我正在寻找一种解决方案来存档数据库中存在的数据 我的数据库是 SQL Server 2008 大约有 250 个表 我搜索网络并找到以下链接 http www dbazine com sql sql articles charran13 h
  • 类型与创建 CLR 存储过程不匹配

    我在程序集中有一个如下所示的方法 namespace MyNameSpace public class MyClass Microsoft SqlServer Server SqlProcedure public static void M
  • 从 Visual Studio 调试 SQL Server 2005 中的存储过程?

    我在这里和其他地方看到很多令人沮丧的问题 但没有明确的答案 我试图让存储过程进行调试 但没有成功 客户端 VS2005或VS2008 两者都不起作用 当我从存储过程上下文菜单中选择 步入存储过程 时 我在调试窗口中看到 已被用户取消 这就是
  • 我应该如何优化 .net 代码中对一个简单存储过程的多次调用?

    我有一个非常简单的存储过程 create procedure spFoo v varchar 50 as insert into tbFoo select v 我有 50 个值要插入到 tbFoo 中 这意味着在我的 c 代码中我调用 sp
  • 工厂模式数据库连接

    我正在尝试使用 MySQL 实现数据库连接上的工厂模式 SQL Server 面临奇怪的错误 你调用的对象是空的 在 SQL 命令对象上 internal class SqlServerDB IDatabase private SqlCon
  • 找出会话的默认 SQL Server 架构

    我需要知道正在执行某些 DDL 的 SQL 脚本中当前的默认架构是什么 我不需要设置架构 但我确实需要将对它的引用 名称或 ID 放入变量中 该脚本可能以 Windows 登录身份运行 因此以下内容还不够 SELECT name defau
  • SQL Server 中不需要的日期时间舍入

    我遇到了一些看起来很奇怪的事情 SQL Server 似乎正在舍入一些DateTime当我将它们保存到时 值不合适datetime列 我怀疑我错过了一些东西 但我找不到它 我正在使用 NET 4 0 针对 SQL Server 2008 运
  • SQL COUNT(*) 返回错误答案

    以下脚本应返回部门名称以及这些部门中的员工人数 营销 行政和销售部门有 0 名员工 但返回值不是 0 而是 1 我怎样才能纠正它 select Department Departments DepartmentID count as Num
  • 左连接,左表中没有重复行

    请看下面的查询 tbl 目录 Content Id Content Title Content Text 10002 New case Study New case Study 10003 New case Study New case S
  • 计算行数并仅获取表中的最后一行

    我有一张桌子叫employeexam其结构和数据是这样的 id course id employee id degree date 1 1 3 8 2013 01 14 2 2 4 15 2013 01 14 3 2 4 17 2013 0
  • 左连接 SQL 求和

    我有两张桌子想要加入 比如说表 a 和表 b 表 b 有许多行指向表 a 表 b 包含价格 实际上是一个购物篮 所以我想要的是表a中的所有记录和表b中的价格之和 我努力了 select a sum b ach sell from booki
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • SQL Server XQuery 返回错误

    我正在 SQL Server 2012 中对 XML 数据类型列执行查询 数据示例如下

随机推荐

  • 如何在 Internet Explorer 中使用控制台日志记录?

    有 IE 的控制台记录器吗 我正在尝试将一堆测试 断言记录到控制台 但我无法在 IE 中执行此操作 您可以通过启动 开发人员工具 F12 来访问 IE8 脚本控制台 单击 脚本 选项卡 然后单击右侧的 控制台 在 JavaScript 代码
  • 使用密码配置跳转/堡垒主机

    我有三个主机 我的本地 ansible 控制器 跳跃 堡垒主机 jump host 对于我的基础设施 我想要针对其运行 ansible 任务的目标主机 target host 只能通过以下方式访问jump host 作为我的库存文件的一部分
  • 通过 Microsoft Graph API 创建 Excel 文件

    有谁知道如何通过 MS Graph API 创建 excel 和 ppt 文件 我们正在尝试利用 MS Graph API 通过单击按钮来创建 word excel ppt 文件 虽然我们找到了如何创建 word 文件 但即使 API 成功
  • Java Final——一个永恒的谜

    suggestBox addKeyUpHandler new KeyUpHandler public void onKeyUp KeyUpEvent event if event getNativeKeyCode KeyCodes KEY
  • 找不到列“dbo”或用户定义函数或聚合“dbo.FN_Split”,或者名称不明确

    我有以下函数 它接受 CSV 和分隔符并将其拆分 ALTER FUNCTION dbo FN Split String varchar max Delimiter char 1 returns temptable TABLE orderId
  • :app:transformClassesWithMultidexlistForDebug 失败

    我已经尝试过以下链接 http developer android com intl es tools building multidex html 意外的顶级异常 com android dex DexException 多个 dex 文
  • 使用 ssh 端口转发运行 Erlang Observer

    我有一个远程 Erlang 节点和本地开发人员的 PC 我想启动本地节点 email protected 启动观察者 调用c nl 1和其他调试操作 我写了这个 bin sh export ERL EPMD PORT 43690 PORT
  • 在 Cocoa 应用程序中每晚使用 WebKit.framework?

    我目前正在 Cocoa 应用程序中使用 WebView 我还想在 webview 特别是 FileReader 中使用 HTML5 文件 API FileReader 在最新版本的 WebKit 中不受支持 但在 WebKit nightl
  • 如何在jsp中对url参数进行加密/编码

    我想对一个URL变量进行加密 这样用户在jsp中传递的信息就无法看到或修改 这是一个示例 URL localhost somewebpage name jsp id 1234 tname Employee March 2013 这里我想对参
  • Spring MVC - HTTP 状态 500 - Servlet loginDispacher 的 Servlet.init() 引发异常

    我做了一个简单的程序 但出现以下错误 我正在使用 Eclipse Kelper 和 Tomcat 7 0 尝试了很多事情 但没有任何对我有用 HTTP 状态 500 servlet loginDispacher 的 Servlet init
  • 根据另一个数据帧的多个列条件创建列

    假设我有两个数据框 条件和数据 import pandas as pd conditions pd DataFrame class 1 2 3 4 4 5 5 4 4 5 5 5 primary lower 0 0 0 160 160 16
  • Python SqlAlchemy - AttributeError:映射器

    基于我的模型 from sqlalchemy ext declarative import declarative base from sqlalchemy import Column Integer String ForeignKey f
  • iOS:如何查询WiFi状态

    是否可以以编程方式查询 iOS 上的 WiFi 状态 启用 禁用 当启用 WiFi 并且设备未连接到任何网络时 查询应返回 true EDIT 我知道提供的功能Reachability类 据我了解 它无法识别 WIFI 的已启用但未连接状态
  • while 循环 PHP get_result 不起作用

    我正在尝试使用 MySQl 准备好的语句从数据库中获取行并获取结果 然而这不起作用 请有人能看到我哪里出了问题吗 我已经尝试了几个小时的解决方案 但无法使其发挥作用 该页面只是不加载 就好像查询失败一样 tag trim GET tag s
  • 部署后在django中使用scipy.stats.stats

    我正在为一个严重依赖 scipy stats stats scipy 版本 0 9 0 的包创建一个由 django 支持的 1 3 接口 称为ovl 在早期开发阶段 使用 djangos 自己的开发服务器 这没有问题 使用apache d
  • 带有 WSDL for R 的 SOAP 客户端

    我正在尝试使用 SSOAP 包为 R 的 SOAP 客户端编写代码 这是我最初的代码 wsdl lt getURL http sistemas cvm gov br webservices Sistemas SCW CDocs WsDown
  • 如何在 WinForms 中绘制形状[重复]

    这个问题在这里已经有答案了 我正在尝试编写类似绘画的程序 您可以通过选择所需的形状来绘制填充形状 单击图片框并拖动鼠标以获得所需的尺寸 但THIS当我拖动时可能会发生 当我使用refresh 之前绘制的形状会自行删除 我应该怎么做才能绘制填
  • 无法创建圆角对话框(Android-Eclipse)

    我正在尝试为我的应用程序的对话框制作自定义对话框形状 我已经搜索这个主题几个小时了 但我找到的解决方案对我不起作用 这就是为什么我向你询问我自己的问题 我想要一个带有圆角并显示标题的对话框 然后是一个带有一些文本的 ScrollView 唯
  • Excel VBA For-Next 循环将数据从一个 WB 提取到另一个 WB

    我正在开发一个 for 循环 该循环根据第 12 列中等于 Airfare 的字符串提取整行数据 这个想法是复制第 12 列 EXPENSE TYPE 是机票的数据行并将其粘贴到第二个工作簿中 我的代码 如下 未正确循环所有 120 行数据
  • 查找忽略重叠的总分钟数(将基于光标的答案转换为 CTE)

    有一个现有问题该问题询问如何查找多个日期范围内有多少分钟 忽略重叠 给出的示例数据是 userID 不是特别相关 Available ID userID availStart availEnd 1 456 2012 11 19 16 00