SQL用于查找从多个重叠间隔开始经过的时间

前端之家收集整理的这篇文章主要介绍了SQL用于查找从多个重叠间隔开始经过的时间前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
不使用MSsql或DB2或Oracle.
没有CTE.
没有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

解决方法

这个sql语句似乎得到了你想要的东西(t是样本表的表名):
SELECT
   d.id,d.duration,d.duration - 
   IFNULL(
      ( SELECT Sum( timestampdiff( sql_TSI_DAY,no_hold.d2,( SELECT min(d1) FROM t t4 
                                     WHERE t4.id = no_hold.id and t4.d1 > no_hold.d2 )))
        FROM ( SELECT DISTINCT id,d2 FROM t t1 
               WHERE ( SELECT sum( IIF( t1.d2 between t2.d1 and t2.d2,1,0 ) ) 
                       FROM t t2 WHERE t2.id = t1.id and t2.d2 <> t1.d2 ) = 0 
             And d2 <> ( select max( d2 ) from t t3 where t3.id = t1.id )) no_hold
        WHERE no_hold.id = d.id ),0 ) "parts hold"
FROM 
   ( SELECT id,timestampdiff( sql_TSI_DAY,min( d1 ),max( d2 ) ) duration
     FROM t GROUP BY id ) d

外部查询获取修复工作的持续时间.复杂子查询计算不等待零件的总天数.这是通过找到车辆没有等待零件的开始日期来完成的,然后计算它开始等待零件的天数:

// 1) The query for finding the starting dates when the vehicle is not waiting for parts,// i.e. finding all d2 that is not within any date range where the vehicle is waiting for part.
// The DISTINCT is needed to removed duplicate starting "no hold" period.

SELECT DISTINCT id,d2 
FROM t t1
WHERE ( SELECT sum( IIF( t1.d2 between t2.d1 and t2.d2,0 ) ) from t t2 
        WHERE t2.id = t1.id and t2.d2 <> t1.d2 ) = 0 AND 
      d2 <> ( SELECT max( d2 ) FROM t t3 WHERE t3.id = t1.id ) )

// 2)车辆没有等待零件的日期是从上述查询到车辆//再次等待零件的日期

timestampdiff( sql_TSI_DAY,( SELECT min(d1) FROM t t4 WHERE t4.id = no_hold.id and t4.d1 > no_hold.d2 ) )

将上述两者结合起来并汇总所有这些时期,可以得出车辆不等待零件的天数.最终查询添加了一个额外条件来计算外部查询中每个id的结果.

在具有许多ID的非常大的表上,这可能不是非常有效.如果id被限制为一个或几个,它应该很好.

原文链接:https://www.f2er.com/mssql/78405.html

猜你在找的MsSQL相关文章