I am trying to solve an issue where I need to find the previous,current and next record where the query matches certain condition. In the example image below I am interested in only records where pattern_id=23587462 (can be multiple), and it the previous machine_id = next machine_id, then fetch the 3 records.
select SL.*, row_number() over (PARTITION BY Machine_id Order by machine_id, SS2k) as M
from SL
where pattern_id in (23587462,2879003)
I am expecting these records plus the previous and the next record too
Update:- with the help of @shawnt00 and @SelVazi, I used their syntax/code and have a modified version as below,
with cte as (Select SL.*, lead(machine_id,1) over (order by machine_id) as lead_mid, lead(pattern_id,1) over (order by machine_id) as lead_pid,
lag(machine_id,1) over (order by machine_id) as lag_mid, lag(pattern_id,1) over (order by machine_id) as lag_pid,
Case
when pattern_id in (23587462) then 'Current'
when lead_pid in (23587462) and machine_id=lead_mid then 'Source'
when lag_pid in (23587462) and machine_id=lag_mid then 'Loss'
End as sourceloss
from SL)
Select * from cte
where sourceloss is not Null;
2
Answers
This is a working solution if the ss2k is unique and take on considération if the machine_id should be the same for pervious current and next record for the selected pattern_id :
First
cte
to get previous and next record using two window functions :Lag()
function to get data of a previous row from the current row.Lead()
function to get data of a previous row from the current row.cte2
to get the machine_id of the previous and next records.cte3
to group records by group of 3 records(previous, current and next), then with a join we get only data from group of 3 records (if length is less than 3 that means one of the records is not in the same machine so ignore the whole group).Demo here
A naive
lead/lag()
method will work here without requiring any joins. It does require that there be three rows in the matching "group" of rows.This does have problems if there are overlapping sets of rows. Take a look at the third set in the example link below for an example of that scenario (with
Machine_ID
of all 9’s.)Another approach eliminates that problem by examining each set of three consecutive rows. In that way the overlaps are no longer a problem. It’s not clear though how you’d want to label those rows:
Both of the queries do assume that
SS2K
is unique for the relevant rows adjacent to the matches.https://dbfiddle.uk/7YU9IB1h