我有一个带有Event_TimeStamp
和FinalStateand
的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编写出来?
可以使用联接。我使用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;
您可以使用滞后功能检查状态是否更改:
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
希望这会有所帮助。
您可以使用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