MySQL查询连续相同的结果

时间:2015-01-27 10:29:32

标签: mysql

table-1
+-----+----------+--------+----------+---------------------+
| id  | isp_name | uptime | downtime | stamp_date          |
+-----+----------+--------+----------+---------------------+
| 581 | AIRCEL   |      0 |      289 | 2015-01-23 10:27:26 |
| 584 | AIRCEL   |    310 |        0 | 2015-01-23 10:32:27 |
| 587 | AIRCEL   |      0 |      297 | 2015-01-23 10:37:28 |
| 590 | AIRCEL   |      0 |      303 | 2015-01-23 10:42:29 |
| 593 | AIRCEL   |      0 |      311 | 2015-01-23 10:47:30 |
| 596 | AIRCEL   |    272 |        0 | 2015-01-23 10:52:31 |
| 599 | AIRCEL   |    300 |        0 | 2015-01-23 10:57:32 |
| 602 | AIRCEL   |      0 |      317 | 2015-01-23 11:02:33 |
| 605 | AIRCEL   |      0 |      287 | 2015-01-23 11:07:34 |
| 608 | AIRCEL   |    317 |        0 | 2015-01-23 11:12:35 |
| 611 | AIRCEL   |    292 |        0 | 2015-01-23 11:17:36 |
| 614 | AIRCEL   |      0 |      292 | 2015-01-23 11:22:37 |
+-----+----------+--------+----------+---------------------+

以上是我的正常运行时间和停机时间结果。

我想仅显示连续的停机时间记录,如下表所示。

table-2
+----------+--------+----------+---------------------+---------------------+
| isp_name | uptime | downtime | start_time          | end_time            |
+----------+--------+----------+---------------------+---------------------+
| AIRCEL   |      0 |      289 | 2015-01-23 10:27:26 | 2015-01-23 10:32:28 |
| AIRCEL   |      0 |      297 | 2015-01-23 10:37:28 | 2015-01-23 10:52:31 |
| AIRCEL   |      0 |      317 | 2015-01-23 11:02:33 | 2015-01-23 11:12:35 |
| AIRCEL   |      0 |      292 | 2015-01-23 11:22:37 | NOW                 |
 +----------+-------+----------+---------------------+---------------------+




    SELECT isp_name,
       interface_up_time AS uptime,
       interface_down_time AS downtime,
       min(stamp_date) AS start_time,
       max(stamp_date) AS end_time
FROM
  (SELECT r.*,
          (@ups := @ups + (interface_up_time = 0)) AS ups,
          (@downs := @downs + (interface_up_time != 0)) AS downs
   FROM interface_stats r
   CROSS JOIN
     (SELECT @ups := 0, @downs := 0) vars
   WHERE isp_name='AIRCEL'
     AND device_id='fmpvd2001100999'
     AND stamp_date >='2015-01-23 10:23:10'
     AND stamp_date <='2015-01-23 11:23:10'
   ORDER BY stamp_date) r
GROUP BY interface_up_time, (CASE
                                 WHEN interface_up_time = 0 THEN downs
                                 ELSE ups
                             END);

我已经尝试了上面的查询并获得了像

这样的结果
table-3
+----------+--------+----------+---------------------+---------------------+
 | isp_name | uptime | downtime | start_time          | end_time           |
+----------+--------+----------+---------------------+---------------------+
| AIRCEL   |      0 |      289 | 2015-01-23 10:27:26 | 2015-01-23 10:27:26 |
| AIRCEL   |      0 |      297 | 2015-01-23 10:37:28 | 2015-01-23 10:47:30 |
| AIRCEL   |      0 |      317 | 2015-01-23 11:02:33 | 2015-01-23 11:07:34 |
| AIRCEL   |      0 |      292 | 2015-01-23 11:22:37 | 2015-01-23 11:22:37 |
| AIRCEL   |    272 |        0 | 2015-01-23 10:52:31 | 2015-01-23 10:52:31 |
| AIRCEL   |    292 |        0 | 2015-01-23 11:17:36 | 2015-01-23 11:17:36 |
| AIRCEL   |    300 |        0 | 2015-01-23 10:57:32 | 2015-01-23 10:57:32 |
| AIRCEL   |    310 |        0 | 2015-01-23 10:32:27 | 2015-01-23 10:32:27 |
| AIRCEL   |    317 |        0 | 2015-01-23 11:12:35 | 2015-01-23 11:12:35 |
+----------+--------+----------+---------------------+---------------------+

你能帮助我取得成果吗?

2 个答案:

答案 0 :(得分:0)

这是一种方式。这得到了所有结果。如果您只想要停机时间,请相应地修改最终的WHERE子句。

SELECT a.isp_name
     , a.status
     , a.duration
     , a.stamp_date start
     , MIN(c.stamp_date) end 
  FROM 
     ( SELECT isp_name
            , CASE WHEN uptime > 0 THEN 'up' ELSE 'down' END status
            , CASE WHEN uptime > 0 THEN uptime ELSE downtime END duration
            , stamp_date
            , @a := @a + 1 seq
         FROM my_table
         JOIN (SELECT @a:=0) vars
     ) a
  LEFT 
  JOIN  
     ( SELECT isp_name
            , CASE WHEN uptime > 0 THEN 'up' ELSE 'down' END status
            , CASE WHEN uptime > 0 THEN uptime ELSE downtime END duration
            , stamp_date
            , @b := @b + 1 seq
         FROM my_table
         JOIN (SELECT @b:=0) vars
     ) b 
    ON b.seq = a.seq - 1
   AND b.isp_name = a.isp_name
   AND b.status = a.status
  LEFT 
  JOIN 
     ( SELECT isp_name
            , CASE WHEN uptime > 0 THEN 'up' ELSE 'down' END status
            , CASE WHEN uptime > 0 THEN uptime ELSE downtime END duration
            , stamp_date
            , @c := @c + 1 seq
         FROM my_table
         JOIN (SELECT @c:=0) vars
     ) c 
    ON c.seq >= a.seq
   AND c.isp_name = a.isp_name
   AND c.status = a.status
  LEFT 
  JOIN 
     ( SELECT isp_name
            , CASE WHEN uptime > 0 THEN 'up' ELSE 'down' END status
            , CASE WHEN uptime > 0 THEN uptime ELSE downtime END duration
            , stamp_date
            , @d := @d + 1 seq
         FROM my_table
         JOIN (SELECT @d:=0) vars
     ) d 
    ON d.seq = c.seq + 1
   AND d.isp_name = a.isp_name
   AND d.status = a.status
 WHERE b.seq IS NULL 
   AND c.seq IS NOT NULL
   AND d.seq IS NULL
 GROUP 
    BY a.seq;

答案 1 :(得分:-1)

我认为这可能是您正在寻找的内容,虽然我只在SQL Server中进行了测试,因为我没有使用MySQL,但应该使用相同的...

SELECT MIN(isp_name) AS isp_name, 
       MIN(uptime) AS uptime, 
       MIN(downtime) AS downtime,
       MIN(start_time) AS start_time,
       end_time FROM

       (SELECT d.isp_name, 
            d.uptime, 
            d.downtime, 
            d.stamp_date AS start_time, 
            COALESCE((SELECT MIN(CAST(u.stamp_date AS VARCHAR(20))) 
                FROM table-1 u 
                WHERE u.stamp_date > d.stamp_date 
                    AND u.uptime > 0), 'NOW') AS end_time 

            FROM table-1 d 
            WHERE d.downtime > 0) down

       GROUP BY end_time;

唯一的问题是将u.stamp_date转换为VARCHAR似乎将end_time转换为&#34;人类可读&#34;格式,我必须做以显示&#34;现在&#34;而不是&#34; NULL&#34; - 我确定是否有方法可以在stackoverflow上找到它... OTOH你可能很高兴只显示&#34; NULL&#34; ....或者在MySQL你可能不需要施展它......

您可以使用ISNULL代替COALESCE,我认为它应该会得到相同的结果。