sql >> データベース >  >> RDS >> Mysql

値が範囲内にある間のmysqlのグループ化

    これを試してください: http://www.sqlfiddle.com/#!2/e9372/ 1

    DB側で実行する利点は、PHPだけでなく、Java、C#、Pythonなどでもクエリを使用できることです。DB側でも高速に実行できます。

    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
    

    出力:

    |    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 |
    

    ここでクエリの進行状況を確認してください: http://www.sqlfiddle.com/#!2 / e9372 / 1

    仕組み:

    5つのステップ。

    まず、アイドル状態と非アイドル状態を分離します。

    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;
    

    出力:

    |                  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 |
    

    次に、変更をグループに分けます。

    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;
    

    出力:

    |                  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 |
    

    第三に、それらをグループ化し、期間を計算します:

    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;
    

    出力:

    | 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 |
    

    第4に、アイドルカウントと非アイドルカウントを取得します。

    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;
    

    出力:

    | 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 |
    

    最後に、ステージング変数を削除します:

    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
    

    出力:

    |    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 |
    

    ここでクエリの進行を参照してください: http://www.sqlfiddle.com/#!2/ e9372 / 1

    更新

    クエリを短縮できます http://www.sqlfiddle.com/#!2/418cb / 1

    お気づきの方もいらっしゃると思いますが、期間番号はタンデムになっています(idle-nonIdle、idle-nonIdleなど)。これを行うことができます:

    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
    

    出力:

    |     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 |
    


    1. サーバーステータスコードを修正する方法:302 SQL InjectMeFirefoxアドオンで見つかりました

    2. SQLDeveloperはXMLを表示しません

    3. dbms_output.put()はdbms_output.put_line()とは異なる方法でバッファリングされていますか?

    4. MySQLは各行の日時を自動保存します