MySQL查询以了解计划合规性

时间:2018-07-23 00:34:01

标签: mysql sql datetime timestamp

我有一张表 Works ,在其中有 开始日期 结束日期 列>是日期时间类型和 qtty tinyint。为了涵盖这些作品,我得到了另一个名为 Turns 的表,该表具有 start_turn end_turn 两种日期时间类型也一样。

需要为大于或等于 qtty 的人数(分配了转弯数)的人遮盖作品,但不一定需要将转弯数从 works.start_date works.end_date

我需要知道的是作品是否被适当地覆盖,我的意思是,是否总是为至少来自 qtty 人覆盖作品?开始日期 结束日期

例如:案例1

工作=> 开始日期 = 2018-07-01 10:00 | 结束日期 = 2018-07-01 22:00 | qtty = 2
转弯=>
人物A: 开始转弯 = 2018-07-01 10:00 | end_turn = 2018-07-01 22:00
人物B: 开始转弯 = 2018-07-01 10:00 | end_turn = 2018-07-01 16:00
人物C: 开始转弯 = 2018-07-01 16:00 | end_turn = 2018-07-01 22:00

案例2

工作=> 开始日期 = 2018-07-01 10:00 | 结束日期 = 2018-07-01 22:00 | qtty = 2
转弯=>
人物A: 开始转弯 = 2018-07-01 10:00 | end_turn = 2018-07-01 22:00
人物B: 开始转弯 = 2018-07-01 16:00 | end_turn = 2018-07-01 22:00
人物C: 开始转弯 = 2018-07-01 16:00 | end_turn = 2018-07-01 22:00

看到第一种情况,我们可以解决该问题,只需提取工作时间乘以 qtty ,然后将该值与每个回合的分钟总和进行比较,然后答案是“是”,则正确地覆盖了工作。但是将这种方法应用于第二种情况,答案也是“是”,但这是不正确的,因为从 开始日期 < em> end_date

我该怎么做?任何帮助将不胜感激。

编辑

这是正确的SQL提琴:http://sqlfiddle.com/#!9/c53d1b

2 个答案:

答案 0 :(得分:1)

不是答案;评论太久了:

Case 1 : Qtty = 2


   10 11 12 13 14 15 16 17 18 19 20 21 22
A  |------------------------------------|
B  |------------------|
C                     |-----------------|

Case 2 : Qtty = 2

   10 11 12 13 14 15 16 17 18 19 20 21 22
A  |------------------------------------|
B                     |-----------------|
C                     |-----------------|

案例2似乎满足了“那些作品不一定需要从works.start_date到works.end_date”的要求

答案 1 :(得分:0)

不是一个完整的答案,只是一个大概的想法。

要解决此问题,您必须开箱即用,以稍微不同的方式提出问题。

  1. 首先,您需要列出所有与时间有关的时间点 您的工作间隔及其相应的转弯 / 班次
  2. 然后您必须删除重复项-即仅保留不同的时间点
  3. 然后,您必须建立一个包含这些时间点之间所有时间间隔的列表-如果您有N个时间点,您将拥有N-1个间隔
  4. 然后对于上述每个间隔,您需要计算有多少转弯 / 平移完全包含此间隔
  5. 如果在上述间隔的每个中,您至少有 qtty 个回合转弯-那么该工作被班次完全覆盖了,否则不是

让我们举两个例子。对于情况1,您有3个时间点-10、16、22。这意味着2个间隔-从10到16和从16到22。对于第一个间隔,您有2个匝数完全包含间隔-A和B。第二个间隔有2个回合,完全包含间隔-A和C。

对于情况2,您具有相同的时间点和相同的子间隔。但是,这一次间隔10-16,您只有1个转弯,完全包含了该间隔-转弯A。因此,在这种情况下,转弯未完全覆盖所需的转弯< / strong>。

我仍然不确定如何在单个SQL查询中实现这一点-也许您将不得不从存储过程开始,以过程的方式通过循环来执行操作,然后在您更好地理解后对其进行优化这个想法。

更新

这里有一些SQL可以为您提供初始近似值,您将根据自己的口味(http://sqlfiddle.com/#!9/72e841/3)进行调整:

select * from
  (select p_start,p_end,qty -
    (select count(*) from turns 
      where start_turn <= p_start 
        and end_turn >= p_end
    ) as non_covered
   from
   (select pt, @start:=@end AS p_start, @end:=pt AS p_end 
     from
     (select start_date as pt from work where id=1
      union 
      select end_date as pt from work where id=1
      union 
      select start_turn from turns, work 
        where work.id=1 
          and start_turn between start_date and end_date
      union 
      select end_turn from turns, work 
        where work.id=1 
          and start_turn between start_date and end_date
     ) as tmp
     order by pt
   ) as period
   join work on work.id = 1
   where p_start <> p_end
  ) as cover
  where non_covered > 0