对具有相同状态的行进行分组,直到更改状态

时间:2017-01-17 09:29:50

标签: mysql

我有下表。对于2.5分钟(150秒),两个工厂有一个记录。我希望得到一个结果,显示工厂的相应状态的最大值(日期时间)和最小值(日期时间)。但是对于状态的每次变化都应该有一条新线。

 plant state  unix_timest   datetime
    1   1     1452639750   2016-01-13 00:02:30
    2   1     1452639750   2016-01-13 00:02:30
    1   1     1452639900   2016-01-13 00:05:00
    2   1     1452639900   2016-01-13 00:05:00
    1   1     1452640050   2016-01-13 00:07:30
    2   1     1452640050   2016-01-13 00:07:30
    1   1     1452640200   2016-01-13 00:10:00
    2   1     1452640200   2016-01-13 00:10:00
    1   1     1452640350   2016-01-13 00:12:30
    2   0     1452640350   2016-01-13 00:12:30
    1   1     1452640500   2016-01-13 00:15:00
    2   0     1452640500   2016-01-13 00:15:00
    1   1     1452640650   2016-01-13 00:17:30
    2   1     1452640650   2016-01-13 00:17:30
    1   1     1452640800   2016-01-13 00:20:00
    2   1     1452640800   2016-01-13 00:20:00

我的SQL语句是:

 SELECT a.line, a.current_state, min( a.`datetime` ) AS mindate, max( a.`datetime` ) AS maxdate
    FROM `bde_production`
    LEFT JOIN bde_production a ON a.unix_timestamp = bde_production.unix_timestamp
    LEFT JOIN bde_production b ON b.unix_timestamp = bde_production.unix_timestamp -150
    GROUP BY a.line, a.current_state   ORDER BY a.line, mindate

结果:

 plant current_state    mindate              maxdate
    1   1              2016-01-13 00:02:30  2016-01-13 00:20:00
    2   1              2016-01-13 00:02:30  2016-01-13 00:20:00
    2   0              2016-01-13 00:12:30  2016-01-13 00:15:00

我希望得到什么:

 plant current_state    mindate              maxdate
    1   1              2016-01-13 00:02:30  2016-01-13 00:20:00
    2   1              2016-01-13 00:02:30  2016-01-13 00:10:00
    2   0              2016-01-13 00:12:30  2016-01-13 00:15:00
    2   1              2016-01-13 00:17:30  2016-01-13 00:20:00

由于

2 个答案:

答案 0 :(得分:0)

同样地,我没有得到正确的结果,但在这里留下我的划痕,以防它有用。我的基本想法是找到所有更改,为它们分配一个id(change_num),并按转换分组。我稍后会修改

CREATE TABLE bde_production (
  `id`          INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `plant`       INT(3) UNSIGNED     NOT NULL,
  `state`       TINYINT(1) UNSIGNED NOT NULL,
  `unix_timest` INT(10) UNSIGNED    NOT NULL,
  `datetime`    DATETIME            NOT NULL
);

INSERT INTO bde_production (plant, state, unix_timest, datetime) VALUES
  (1, 1, 1452639750, "2016-01-13 00:02:30"),
  (2, 1, 1452639750, "2016-01-13 00:02:30"),
  (1, 1, 1452639900, "2016-01-13 00:05:00"),
  (2, 1, 1452639900, "2016-01-13 00:05:00"),
  (1, 1, 1452640050, "2016-01-13 00:07:30"),
  (2, 1, 1452640050, "2016-01-13 00:07:30"),
  (1, 1, 1452640200, "2016-01-13 00:10:00"),
  (2, 1, 1452640200, "2016-01-13 00:10:00"),
  (1, 1, 1452640350, "2016-01-13 00:12:30"),
  (2, 0, 1452640350, "2016-01-13 00:12:30"),
  (1, 1, 1452640500, "2016-01-13 00:15:00"),
  (2, 0, 1452640500, "2016-01-13 00:15:00"),
  (1, 1, 1452640650, "2016-01-13 00:17:30"),
  (2, 1, 1452640650, "2016-01-13 00:17:30"),
  (1, 1, 1452640800, "2016-01-13 00:20:00"),
  (2, 1, 1452640800, "2016-01-13 00:20:00");


SET @line_num_a = 0;
SET @line_num_b = 0;
SET @change_num = 0;

SELECT plant,
  IFNULL(`changes_max_state`, `bde_max_state`) AS `current_state`,
  `bde_min_date`,
  IFNULL(`changes_max_date`, `bde_max_date`),
  `changes_max_date`,
  `bde_max_date`
FROM (
       SELECT
         bde.plant,
         change_num,
         MIN(bde.datetime) `bde_min_date`,
         MAX(bde.datetime) `bde_max_date`,
         MAX(bde.state) `bde_max_state`,
         MIN(changes.datetime) `changes_min_date`,
         MAX(changes.state) `changes_max_state`,
         MAX(changes.datetime) `changes_max_date`-- MIN(bde.datetime), MAX(bde.datetime)
         , MIN(changes.datetime_b),
         MAX(changes.datetime_b)
       FROM
         bde_production bde LEFT JOIN (
                                        SELECT
                                          # a.datetime is the max reading for plant in a.state
                                          b.*, a.datetime AS datetime_b, @change_num := @change_num + 1 `change_num`
                                        FROM
                                          (
                                            SELECT
                                              *,
                                              @line_num_a := @line_num_a + 1 AS `line`
                                            FROM (
                                                   SELECT *
                                                   FROM bde_production
                                                   ORDER BY plant DESC
                                                 ) a1) a
                                          JOIN (
                                                 SELECT
                                                   *,
                                                   @line_num_b := @line_num_b + 1 AS `line`
                                                 FROM (
                                                        SELECT *
                                                        FROM bde_production
                                                        ORDER BY plant DESC
                                                      ) b1) b
                                            ON
                                              a.plant = b.plant AND a.line = b.line - 1 AND a.state <> b.state
                                      ) changes
           ON changes.plant=bde.plant AND bde.id > changes.id
       GROUP BY change_num, plant
     ) q
; 

答案 1 :(得分:-1)

我几乎得到了结果:

    SELECT
        d.plant, d.current_state, d.unix_timestamp, d.`datetime`
    FROM
        bde_production d
           left join
        bde_production d_prev
           on
             d_prev.line = d.line and  
             d_prev.unix_timestamp< (d.unix_timestamp)
           left join
        bde_production d_inter
           on
               d_prev.plant= d.plant and 
               d_inter.unix_timestamp< (d.unix_timestamp) and
               d_prev.unix_timestamp< (d_inter.unix_timestamp) 

    WHERE
        d_inter.unix_timestamp is null AND
        (d_prev.current_state is null OR d_prev.current_state <> d.current_state

)

结果:

line    current_state   unix_timestamp  datetime
1        1                1452639750    2016-01-13 00:02:30
2        1                1452639750    2016-01-13 00:02:30
2        0                1452640350    2016-01-13 00:12:30
2        1                1452640650    2016-01-13 00:17:30

我只想添加一个列,其中包含current_state更改的下一行的datetime