如何获得在MYSQL8中更改列值之前首次出现的选择行

问题描述 投票:2回答:3

我有一个带有Event_TimeStampFinalStateand的MYSQL8表,看起来像这样

+---------------------------+---------------+
|"Event_TimeStamp"          |"FinalState"   |
+---------------------------+---------------+
|"2020-03-09 04:57:45.729"  |"Available"    |
|"2020-03-09 05:14:59.659"  |"Available"    |
|"2020-03-09 05:27:56.341"  |"Available"    |
|"2020-03-09 05:41:01.554"  |"Available"    |
|"2020-03-09 05:58:07.803"  |"Available"    |
|"2020-03-09 06:06:09.745"  |"Available"    |
|"2020-03-09 06:18:07.663"  |"Available"    |
|"2020-03-09 06:26:24.273"  |"Available"    |
|"2020-03-09 09:29:53.165"  |"Offline"      |
|"2020-03-09 10:28:00.514"  |"Available"    |
|"2020-03-09 12:47:54.130"  |"Available"    |
|"2020-03-09 13:01:30.117"  |"Available"    |
|"2020-03-09 13:01:59.774"  |"Offline"      |
|"2020-03-09 13:19:15.772"  |"Available"    |
|"2020-03-09 14:19:51.521"  |"Available"    |
|"2020-03-09 14:50:16.872"  |"Offline"      |
+---------------------------+---------------+

我必须从上面提取行,以使行具有第一个“ Available”和“ Offline”,所以输出看起来像这样

+---------------------------+---------------+
|"Event_TimeStamp"          |"FinalState"   |
+---------------------------+---------------+
|"2020-03-09 04:57:45.729"  |"Available"    |
|"2020-03-09 09:29:53.165"  |"Offline"      |
|"2020-03-09 10:28:00.514"  |"Available"    |
|"2020-03-09 13:01:59.774"  |"Offline"      |
|"2020-03-09 13:19:15.772"  |"Available"    |
|"2020-03-09 14:50:16.872"  |"Offline"      |
+---------------------------+---------------+

我用GROUP BY尝试了几种方法,但是我只获得每个FinalState的前一个条目,而其余的则没有。

是否有办法通过QUERY完成此操作,还是应该用PHP编写出来?

mysql sql window-functions gaps-and-islands mysql-8.0
3个回答
0
投票

可以使用联接。我使用events作为数据库名称示例。

SELECT x.* 
  FROM events x
  JOIN
     (
       SELECT MIN(c.id) id 
         FROM events a
         LEFT 
         JOIN events b 
           ON b.FinalState = a.FinalState 
          AND b.id = a.id - 1 
         LEFT 
         JOIN events c 
           ON c.FinalState = a.FinalState
          AND c.id >= a.id
         LEFT
         JOIN events d
           ON d.FinalState = a.FinalState
          AND d.id = c.id + 1
        WHERE b.id IS NULL 
          AND c.id IS NOT NULL
          AND d.id IS NULL
        GROUP 
           BY a.id
     ) y
    ON y.id = x.id; 

0
投票

您可以使用滞后功能检查状态是否更改:

with cte as
(select CAST('2020-03-09 04:57:45.729' as datetime) as Event_timestamp,'Available' as Finalstate union
select '2020-03-09 05:14:59.659','Available' union
select '2020-03-09 09:29:53.165','Offline' union
select '2020-03-09 10:28:00.514','Available')

select x.Event_timestamp,x.Finalstate
from
(select *,lag(Finalstate) Over(Order by Event_timestamp) as lag_status
from cte ) x
where x.Finalstate<>coalesce(lag_status,'Z')

这里是数据库小提琴:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=cb59ec79e7be1363961971cea4308dff

希望这会有所帮助。


0
投票

您可以使用lag()lead()展示其final_state与上一行或下一行不同的记录:

select
    event_timestamp,
    final_state
from (
    select 
        t.*, 
        lag(final_state) over(order by event_timestamp)  lag_final_state,
        lead(final_state) over(order by event_timestamp) lead_final_state
    from mytable t
) t
where final_state <> lag_final_state or final_state <> lead_final_state
© www.soinside.com 2019 - 2024. All rights reserved.