i'm wondering if someone can help me out with this one
I have the following query :
SELECT * FROM `E935308` WHERE date BETWEEN '2015-09-03' AND '2015-09-03' ORDER BY date, time, id
The result would be like this:
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
There are four events (4, 5, 45 and 46) Assuming that : 4 = START, 5 = STOP, 45 = IN and 46 = OUT
I need an algorithm to show me the time of the very first event number 4, and after that the time of the first 45 after 4 and 46 that comes right after 45 and at last the first 5 after event 46.
Here is a working example:
2015-09-03 23327 24195 26370 27152
2015-09-03 28407 30428 30449 -
2015-09-03 28407 30514 30540 -
the dash means event 5 doesn't exist.
I don't know if this is possible, still worth asking for.
Thanks for the help.
EDIT:
To make it a little bit clear, how to eliminate the numbers that are not in brackets?
[4]
5
4
5
4
[45]
5
4
5
4
[46]
[5]
4
5
EDIT: first solution was wrong.
There could be more elegant solutions, but here with only 4 events you can get it in a single scan with 5 variables.
This solution dies when you have joins, so if so you must encapsulate all the joins and orders in an inner subselect, so that the variables-magic just happens on a clear single ordered stream of data. All the queries must be sent in the same SQL Connection, otherwise you will lose the variables of course.
If you leave out the outer select and just use the inner select, you see that there is no real magic happening, just simple if-then in MySQL.
Additional info, you can even modify this to measure times between In and Out.
The fiddle shows how it works, and fiddle gets the results. In your example you forgot the touple 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;
This gives
first4 current45 first46 max(first5)
23327 24195 26370 27152
28407 30428 30449 0
28407 30514 30540 0
28407 30555 30617 0
as results.
I hope you see your "state machine" in the setting and resetting of the variables. I must add and subtract @found45
in order to set @current45
, but not to disturb @found46
.
Here is a php solution based on the answer of flaschenpost i know it's not a great one but it's close to what i need. still only one problem.
$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;
}
}
The result is:
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
As you can see there might be a case where we don't have events 4 and 5 so we must show only events 45 and 46.
Any help is appreciated.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.