Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Gruppierung, während sich ein Wert in einem Bereich befindet

Versuchen Sie Folgendes:http://www.sqlfiddle.com/#!2/e9372/ 1

Der Vorteil auf der DB-Seite ist, dass Sie die Abfrage nicht nur auf PHP, sondern auch auf Java, C#, Python usw. verwenden können. Und es geht schnell auf der DB-Seite

select 
  if(idle_state = 1, 
       concat('Idle ', idle_count), 
       concat('NonIdle ', non_idle_count) ) as Period,
  startTime, endTime, duration
from
(

  select 

    @idle_count := @idle_count + if(idle_state = 1,1,0) as idle_count,
    @non_idle_count := @non_idle_count +if(idle_state = 0,1,0) as non_idle_count,

    state_group, idle_state,
    min(timeStamp) as startTime, max(timeStamp) as endTime,
    timestampdiff(second, min(timeStamp), max(timeStamp)) as duration
  from
  (
    select *,        
      @idle_state := if(rpm between 800 and 900, 1, 0) as idle_state,
      @state_group := @state_group + 
                      if(@idle_state = @prev_state,0,1) as state_group,
      @prev_state := @idle_state
    from (tbl, (select @state_group := 0 as y) as vars)
    order by tbl.timeStamp
  ) as x
  ,(select @idle_count := 0 as y, @non_idle_count := 0 as z) as vars
  group by state_group, idle_state

) as summary

Ausgabe:

|    PERIOD |                  STARTTIME |                    ENDTIME | DURATION |
|-----------|----------------------------|----------------------------|----------|
|    Idle 1 | May, 01 2012 01:02:56-0700 | May, 01 2012 01:05:55-0700 |      179 |
| NonIdle 1 | May, 01 2012 01:07:00-0700 | May, 01 2012 01:10:15-0700 |      195 |
|    Idle 2 | May, 01 2012 01:11:20-0700 | May, 01 2012 01:14:20-0700 |      180 |
| NonIdle 2 | May, 01 2012 01:15:20-0700 | May, 01 2012 01:15:20-0700 |        0 |

Sehen Sie sich hier den Abfragefortschritt an:http://www.sqlfiddle.com/#!2 /e9372/1

Wie es funktioniert:

Fünf Schritte.

Trennen Sie zuerst den Leerlauf vom Nicht-Leerlauf:

select *,
  @idle_state := if(rpm between 800 and 900, 1, 0) as idle_state
from (tbl, (select @state_group := 0 as y) as vars)
order by tbl.timeStamp;

Ausgabe:

|                  TIMESTAMP |  RPM | Y | IDLE_STATE |
|----------------------------|------|---|------------|
| May, 01 2012 01:02:56-0700 |  802 | 0 |          1 |
| May, 01 2012 01:03:45-0700 |  845 | 0 |          1 |
| May, 01 2012 01:04:50-0700 |  825 | 0 |          1 |
| May, 01 2012 01:05:55-0700 |  810 | 0 |          1 |
| May, 01 2012 01:07:00-0700 | 1000 | 0 |          0 |
| May, 01 2012 01:08:03-0700 | 1005 | 0 |          0 |
| May, 01 2012 01:09:05-0700 | 1145 | 0 |          0 |
| May, 01 2012 01:10:15-0700 | 1110 | 0 |          0 |
| May, 01 2012 01:11:20-0700 |  800 | 0 |          1 |
| May, 01 2012 01:12:22-0700 |  812 | 0 |          1 |
| May, 01 2012 01:13:20-0700 |  820 | 0 |          1 |
| May, 01 2012 01:14:20-0700 |  820 | 0 |          1 |
| May, 01 2012 01:15:20-0700 | 1200 | 0 |          0 |

Zweitens, teilen Sie die Änderungen in Gruppen auf:

select *,  
  @idle_state := if(rpm between 800 and 900, 1, 0) as idle_state,
  @state_group := @state_group + 
                  if(@idle_state = @prev_state,0,1) as state_group,
  @prev_state := @idle_state

from (tbl, (select @state_group := 0 as y) as vars)
order by tbl.timeStamp;

Ausgabe:

|                  TIMESTAMP |  RPM | Y | IDLE_STATE | STATE_GROUP | @PREV_STATE := @IDLE_STATE |
|----------------------------|------|---|------------|-------------|----------------------------|
| May, 01 2012 01:02:56-0700 |  802 | 0 |          1 |           1 |                          1 |
| May, 01 2012 01:03:45-0700 |  845 | 0 |          1 |           1 |                          1 |
| May, 01 2012 01:04:50-0700 |  825 | 0 |          1 |           1 |                          1 |
| May, 01 2012 01:05:55-0700 |  810 | 0 |          1 |           1 |                          1 |
| May, 01 2012 01:07:00-0700 | 1000 | 0 |          0 |           2 |                          0 |
| May, 01 2012 01:08:03-0700 | 1005 | 0 |          0 |           2 |                          0 |
| May, 01 2012 01:09:05-0700 | 1145 | 0 |          0 |           2 |                          0 |
| May, 01 2012 01:10:15-0700 | 1110 | 0 |          0 |           2 |                          0 |
| May, 01 2012 01:11:20-0700 |  800 | 0 |          1 |           3 |                          1 |
| May, 01 2012 01:12:22-0700 |  812 | 0 |          1 |           3 |                          1 |
| May, 01 2012 01:13:20-0700 |  820 | 0 |          1 |           3 |                          1 |
| May, 01 2012 01:14:20-0700 |  820 | 0 |          1 |           3 |                          1 |
| May, 01 2012 01:15:20-0700 | 1200 | 0 |          0 |           4 |                          0 |

Gruppieren Sie sie drittens und berechnen Sie die Dauer:

select 
  state_group, idle_state,
  min(timeStamp) as startTime, max(timeStamp) as endTime,
  timestampdiff(second, min(timeStamp), max(timeStamp)) as duration
from
(
  select *,    
    @idle_state := if(rpm between 800 and 900, 1, 0) as idle_state,
    @state_group := @state_group + 
                    if(@idle_state = @prev_state,0,1) as state_group,
    @prev_state := @idle_state
  from (tbl, (select @state_group := 0 as y) as vars)
  order by tbl.timeStamp
) as x
group by state_group, idle_state;

Ausgabe:

| STATE_GROUP | IDLE_STATE |                  STARTTIME |                    ENDTIME | DURATION |
|-------------|------------|----------------------------|----------------------------|----------|
|           1 |          1 | May, 01 2012 01:02:56-0700 | May, 01 2012 01:05:55-0700 |      179 |
|           2 |          0 | May, 01 2012 01:07:00-0700 | May, 01 2012 01:10:15-0700 |      195 |
|           3 |          1 | May, 01 2012 01:11:20-0700 | May, 01 2012 01:14:20-0700 |      180 |
|           4 |          0 | May, 01 2012 01:15:20-0700 | May, 01 2012 01:15:20-0700 |        0 |

Viertens erhalten Sie die Leerlauf- und Nicht-Leerlauf-Zählung:

select 

  @idle_count := @idle_count + if(idle_state = 1,1,0) as idle_count,
  @non_idle_count := @non_idle_count + if(idle_state = 0,1,0) as non_idle_count,

  state_group, idle_state,
  min(timeStamp) as startTime, max(timeStamp) as endTime,
  timestampdiff(second, min(timeStamp), max(timeStamp)) as duration
from
(
  select *,        
    @idle_state := if(rpm between 800 and 900, 1, 0) as idle_state,
    @state_group := @state_group + 
                    if(@idle_state = @prev_state,0,1) as state_group,
    @prev_state := @idle_state
  from (tbl, (select @state_group := 0 as y) as vars)
  order by tbl.timeStamp
) as x
,(select @idle_count := 0 as y, @non_idle_count := 0 as z) as vars
group by state_group, idle_state;

Ausgabe:

| IDLE_COUNT | NON_IDLE_COUNT | STATE_GROUP | IDLE_STATE |                  STARTTIME |                    ENDTIME | DURATION |
|------------|----------------|-------------|------------|----------------------------|----------------------------|----------|
|          1 |              0 |           1 |          1 | May, 01 2012 01:02:56-0700 | May, 01 2012 01:05:55-0700 |      179 |
|          1 |              1 |           2 |          0 | May, 01 2012 01:07:00-0700 | May, 01 2012 01:10:15-0700 |      195 |
|          2 |              1 |           3 |          1 | May, 01 2012 01:11:20-0700 | May, 01 2012 01:14:20-0700 |      180 |
|          2 |              2 |           4 |          0 | May, 01 2012 01:15:20-0700 | May, 01 2012 01:15:20-0700 |        0 |

Entfernen Sie abschließend die Staging-Variablen:

select 
  if(idle_state = 1, 
       concat('Idle ', idle_count), 
       concat('NonIdle ', non_idle_count) ) as Period,
  startTime, endTime, duration
from
(

  select 

    @idle_count := @idle_count + if(idle_state = 1,1,0) as idle_count,
    @non_idle_count := @non_idle_count +if(idle_state = 0,1,0) as non_idle_count,

    state_group, idle_state,
    min(timeStamp) as startTime, max(timeStamp) as endTime,
    timestampdiff(second, min(timeStamp), max(timeStamp)) as duration
  from
  (
    select *,        
      @idle_state := if(rpm between 800 and 900, 1, 0) as idle_state,
      @state_group := @state_group + 
                      if(@idle_state = @prev_state,0,1) as state_group,
      @prev_state := @idle_state
    from (tbl, (select @state_group := 0 as y) as vars)
    order by tbl.timeStamp
  ) as x
  ,(select @idle_count := 0 as y, @non_idle_count := 0 as z) as vars
  group by state_group, idle_state

) as summary

Ausgabe:

|    PERIOD |                  STARTTIME |                    ENDTIME | DURATION |
|-----------|----------------------------|----------------------------|----------|
|    Idle 1 | May, 01 2012 01:02:56-0700 | May, 01 2012 01:05:55-0700 |      179 |
| NonIdle 1 | May, 01 2012 01:07:00-0700 | May, 01 2012 01:10:15-0700 |      195 |
|    Idle 2 | May, 01 2012 01:11:20-0700 | May, 01 2012 01:14:20-0700 |      180 |
| NonIdle 2 | May, 01 2012 01:15:20-0700 | May, 01 2012 01:15:20-0700 |        0 |

Siehe Abfragefortschritt hier:http://www.sqlfiddle.com/#!2/ e9372/1

AKTUALISIEREN

Abfrage könnte verkürzt werden http://www.sqlfiddle.com/#!2/418cb /1

Wie Sie bemerken werden, kommt die Periodennummer einfach zusammen (idle-nonIdle,idle-nonIdle usw.). Sie können einfach dies tun:

select 


  case when idle_state then
     concat('Idle ', @rn := @rn + 1) 
  else
     concat('Non-idle ', @rn )
  end as Period,


  min(timeStamp) as startTime, max(timeStamp) as endTime,

  timestampdiff(second, min(timeStamp), max(timeStamp)) as duration

from
(
  select *,        
  @idle_state := if(rpm between 800 and 900, 1, 0) as idle_state,
  @state_group := @state_group + if(@idle_state = @prev_state,0,1) as state_group,
  @prev_state := @idle_state
  from (tbl, (select @state_group := 0 as y) as vars)
  order by tbl.timeStamp
) as x,
(select @rn := 0) as rx
group by state_group, idle_state

Ausgabe:

|     PERIOD |                  STARTTIME |                    ENDTIME | DURATION |
|------------|----------------------------|----------------------------|----------|
|     Idle 1 | May, 01 2012 01:02:56-0700 | May, 01 2012 01:05:55-0700 |      179 |
| Non-idle 1 | May, 01 2012 01:07:00-0700 | May, 01 2012 01:10:15-0700 |      195 |
|     Idle 2 | May, 01 2012 01:11:20-0700 | May, 01 2012 01:14:20-0700 |      180 |
| Non-idle 2 | May, 01 2012 01:15:20-0700 | May, 01 2012 01:15:20-0700 |        0 |