Essentially, you do the same thing with the fields swapped, however, I had to add extra logic to deal with null values since the mvexpand will remove these rows. You may need to do the same for the NewContents depending on your data. | makeresults
| eval RoleContents = "a;b;c"
| eval _time = now()
| append [| makeresults | eval RoleContents="b;c;d" | eval _time=now()-10]
| append [| makeresults | eval RoleContents="a;d" | eval _time =now()-20]
| streamstats current=f window=1 first(RoleContents) as LastRoleContents
| sort _time
| streamstats current=f window=1 first(RoleContents) as PrevRoleContents
| sort - _time
| makemv delim=";" RoleContents
| makemv delim=";" PrevRoleContents
| fields RoleContents PrevRoleContents
| streamstats count as row
| mvexpand RoleContents
| eval NewContents=if(isnull(mvfind(PrevRoleContents, RoleContents)),RoleContents,null)
| stats values(PrevRoleContents) as PrevRoleContents list(RoleContents) as RoleContents list(NewContents) as NewContents by row
| fillnull value="not available" PrevRoleContents
| mvexpand PrevRoleContents
| eval PrevRoleContents=if(PrevRoleContents="not available",null,PrevRoleContents)
| eval RemovedContents=if(isnull(mvfind(RoleContents, PrevRoleContents)),PrevRoleContents,null)
| stats list(PrevRoleContents) as PrevRoleContents values(RoleContents) as RoleContents values(NewContents) as NewContents list(RemovedContents) as RemovedContents by row
| table RoleContents, PrevRoleContents, NewContents, RemovedContents
... View more