根据日期和时间列出事件

时间:2015-09-03 19:19:17

标签: php mysql algorithm

我想知道是否有人可以帮我解决这个问题

我有以下查询:

SELECT * FROM `E935308` WHERE date BETWEEN '2015-09-03' AND '2015-09-03' ORDER BY date, time, id

结果如下:

date        time    event
2015-09-03  23327   4
2015-09-03  23402   5
2015-09-03  23434   4
2015-09-03  23991   5
2015-09-03  24030   4
2015-09-03  24195   45
2015-09-03  24210   5
2015-09-03  24627   4
2015-09-03  24634   5
2015-09-03  26348   4
2015-09-03  26370   46
2015-09-03  27152   5
2015-09-03  28407   4
2015-09-03  28408   5
2015-09-03  29856   4
2015-09-03  30428   45
2015-09-03  30449   46
2015-09-03  30514   45
2015-09-03  30540   46
2015-09-03  30555   45
2015-09-03  30617   46
2015-09-03  30631   45

有四个事件(4,5,45和46) 假设:4 = START,5 = STOP,45 = IN,46 = OUT

我需要一个算法来向我显示第一个事件编号4的时间,然后是在45之后的第4个和第46个之后的前45个时间以及事件46之后的前5个时间。

这是一个有效的例子:

2015-09-03  23327   24195   26370   27152
2015-09-03  28407   30428   30449   -
2015-09-03  28407   30514   30540   -

破折号表示事件5不存在。

我不知道这是否可行,仍然值得一试。

感谢您的帮助。

编辑:

为了清楚一点,如何消除括号内的数字?

[4]
5
4
5
4
[45]
5
4
5
4
[46]
[5]
4
5

2 个答案:

答案 0 :(得分:1)

编辑:第一个解决方案是错误的。

可能有更优雅的解决方案,但这里只有4个事件,您可以通过5个变量进行单次扫描。

当你有连接时,这个解决方案就会消失,所以如果是这样的话,你必须在内部子选择中封装所有连接和顺序,这样变量 - 魔法就会发生在一个清晰的单个有序数据流上。所有查询必须在同一SQL连接中发送,否则您将失去变量。

如果你忽略外部选择而只是使用内部选择,你会看到没有真正的魔法发生,只是简单的if-then在MySQL中。

其他信息,你甚至可以修改它来测量In和Out之间的时间。

fiddle显示其工作原理,fiddle获取结果。在您的示例中,您忘记了tou 128407, 30555, 30617, -1

set @found4=0;
set @found5=0;
set @found45=0;
set @found46=0;
set @current45=0;

select first4, current45, first46, max(first5)
  from (
      select `date`, `time`, event, @found4:=if(event=4 and @found4=0, time+@found5 := 0, @found4) as first4, 
      @found45:=if(event=45 and @found4>0 and @found45=0,  time + @found46 := 0, @found45) as first45,
      @found46:=if(event=46 and @found4>0 and @found45>0 and @found46 = 0,  time + (@current45:=@found45) - @found45 + @found45 :=0, @found46) as first46,
      @current45 as current45,
      @found5:=if(event=5 and @found4>0 and @found46 > 0 and @found5 = 0, time + @found4:=0 + @found45 := 0 + @found46 := 0, @found5 ) as first5
      from t0 order by `date`, `time`
      ) as innersel where first4>0 and first46 > 0 group by first4, current45, first46;

这给出了

first4  current45   first46     max(first5)
23327   24195       26370       27152
28407   30428       30449       0
28407   30514       30540       0
28407   30555       30617       0

结果。

我希望您在设置和重置变量时看到“状态机”。我必须添加和减去@found45才能设置@current45,但不能打扰@found46

答案 1 :(得分:0)

这是一个基于flaschenpost答案的php解决方案我知道它并不是一个伟大的,但它接近我需要的。仍然只有一个问题。

    $req="SELECT * FROM t0 WHERE date BETWEEN '2015-09-03' AND '2015-09-03' ORDER BY date, time, id";
    $q = $conn->prepare($req);
    $q->execute();

    $event1 = 0;
    $event2 = 0;
    $event3 = 0;
    $event4 = 0;
    while($r=$q->fetch()){

        if($r['event'] == 4 and $event1 == 0) {
            echo $r['time'] . ' - ' . $r['event'] . '<br>';
            $event1 = 1;
            $event2 = 0;
            $event3 = 0;
            $event4 = 0;
        }

        if($r['event'] == 45 and $event1 == 1) {
            echo $r['time'] . ' - ' . $r['event'] . '<br>';
            $event1 = 1;
            $event2 = 1;
            $event3 = 0;
            $event4 = 0;
        }

        if($r['event'] == 46 and $event1 == 1) {
            echo $r['time'] . ' - ' . $r['event'] . '<br>';
            $event1 = 1;
            $event2 = 1;
            $event3 = 1;
            $event4 = 0;
        }

        if($r['event'] == 5 and $event1 == 1 and $event2 == 1 and $event3 == 1) {
            echo $r['time'] . ' - ' . $r['event'] . '<br><br>';
            $event1 = 0;
            $event2 = 0;
            $event3 = 0;
            $event4 = 0;
        }
    }

结果是:

    23327 - 4      -> Start Event 1
    24195 - 45
    26370 - 46
    27152 - 5      -> End Event 1

    28407 - 4      -> Start Event 2
    30428 - 45
    30449 - 46      -> This must be considered the End of Event 2    
    30514 - 45      -> This must be considered the Start of Event 3
    30540 - 46      -> This must be considered the End of Event 3
    30555 - 45
    30617 - 46
    30631 - 45
    30687 - 46
    30723 - 45
    34059 - 46
    34073 - 45
    34479 - 46
    34499 - 5

    34660 - 4
    34665 - 45
    35007 - 46
    35009 - 45
    36505 - 45
    36505 - 46
    36525 - 5

    47085 - 4

正如您所看到的,可能存在我们没有事件4和5的情况,因此我们必须仅显示事件45和46。

感谢任何帮助。