SQL查找多个重叠间隔所经过的时间
不使用 MSSQL、DB2 或 Oracle。 无热膨胀系数。 没有 OVERLAP 谓词。 无 INTERVAL 数据类型。 情况:待修车辆上工作无法开始 为该工作订购的所有零件均已收到。 在开始维修之前,可以多次订购零件。 我们需要提取车辆处于“零件保留”状态的时间,
因此对于标识为 id = 1 的车辆 零件在 4 个不同的场合订购 (d1) 和接收 (d2)
ID d1 d2
1 8/1 8/8
1 8/2 8/6
1 8/12 8/14
1 8/3 8/10
8/1 8/8
d1 d2
|-------------------------------|
8/2 8/6 8/12 8/14
d1 d2 d1 d2
|---------------| |----------|
8/3 8/10
d1 d2
|---------------------|
8/1 8/14
|---------------------------------------------------------| = 13 days
8/10 8/12
|--------------------------------------| + |----------| = parts hold = 11 days
从上图可以看出,开始工作的等待时间(假设 8/1 为 车辆可用于工作的日期)为 13 天。 实际等待零件的时间是11天,这个数字 我们需要从数据中得出。 实际的日期时间数据将是我们将从中提取小时数的时间戳, 为了简化演示,我们在此示例数据中使用了日期。 我们正在努力生成一个基于集合(不是 psm、不是 udf、不是游标)的解决方案。 TIA
Not using MSSQL or DB2 or Oracle.
No CTE.
No OVERLAP predicate.
No INTERVAL data type.
The situation: on a vehicle to be repaired work can not start until
all parts ordered for the job have been received.
Parts may be ordered multiple times prior to the start of repair.
We need to extract the time for which the vehicle was on "parts hold"
So for a vehicle identified as id = 1
parts were ordered (d1) and received (d2) on 4 different occasions
ID d1 d2
1 8/1 8/8
1 8/2 8/6
1 8/12 8/14
1 8/3 8/10
8/1 8/8
d1 d2
|-------------------------------|
8/2 8/6 8/12 8/14
d1 d2 d1 d2
|---------------| |----------|
8/3 8/10
d1 d2
|---------------------|
8/1 8/14
|---------------------------------------------------------| = 13 days
8/10 8/12
|--------------------------------------| + |----------| = parts hold = 11 days
As seen from above, the wait time to start work (assuming 8/1 as the
date from which the vehicle was available for work) was 13 days.
The actual time spent waiting for parts was 11 days, which is the number
we need to derive from the data.
The actual datetime data will be timestamps from which we will extract hours,
we used dates in this sample data for simplicity of presentation.
We are struggling to generate a set (not psm, not udf, not cursor) based solution.
TIA
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我无法让@Alex W 的查询正常工作。它不是标准 SQL,因此需要大量重写才能与 SQL Server 兼容(我可以测试)。但它确实给了我一些启发,我对此进行了扩展。
查找每个不间断等待时间段的所有起点:
终点的等效值:
n
是自某个公共时间点以来的天数。起点具有负值,终点具有正值。这样我们就可以将它们相加以获得中间的天数。最后,我们只需要添加内容:
输入表(订单):
输出:
或者,您可以使用存储过程来完成此操作。
调用它:
I couldn't get @Alex W's queries to work. It is not standard SQL, so it required a lot of rewrite to be compatible with SQL Server (which I can test). But it did give me some inspiration, which I have expanded upon.
Find all start-points of every period of uninterrupted waiting:
And the equivalent for end-points:
n
is the number of days since some common point in time. Start-points have a negative value, and end-points have a positive value. This is so that we can just add them up to get the number of days in between.Finally, we just need to add things up:
Input table (Orders):
Output:
Alternatively, you can do this with a stored procedure.
Call it with:
这个SQL语句似乎得到了你想要的(t是样本表的表名):
外部查询得到了修复工作的持续时间。复杂子查询计算不等待零件的总天数。这是通过找到车辆不等待零件的开始日期,然后计算直到再次开始等待零件的天数来完成的:
// 2) 车辆不等待零件的天数是日期从上面的查询直到车辆再次等待零件
将以上两者结合起来并汇总所有此类时间段即可得出车辆不等待零件的天数。最终查询添加了一个额外的条件来计算外部查询中每个 id 的结果。
对于具有许多 id 的非常大的表来说,这可能不是非常有效。如果 id 限制为一个或几个应该没问题。
This SQL statement seems to get what you want (t is the table name of the sampe table):
The outer query gets the duration of the repair work. The complex subquery calculates the total number of days not waiting for parts. This is done by locating the start dates where the vehicle is not waiting for parts, and then count the number of days until it begins to wait for parts again:
// 2) The days where it vehicle is not waiting for part is the date from the above query till the vehicle is // waiting for part again
Combining the two above and aggregating all such periods gives the number of days that the vehicle is not waiting for parts. The final query adds an extra condition to calculate result for each id from the outer query.
This probably is not terribly efficient on very large table with many ids. It should fine if the id is limited to one or just a few.