Home > Software engineering >  SQL - LAG but skip specific rows based on value?
SQL - LAG but skip specific rows based on value?

Time:07-13

I have the below table. What I am trying to do is add a LAG column which shows me the previous [EndDate] for ONLY entries that have a status that isn't 6. 6 means inactive.. so I don't want to count them.

SPID        ID            Status       StartDate                 EndDate   
29333       102             7         01 jan 2013              1 Jan 2014
29333       202             6         7 Jun 2021               15 Jun 2022
29333       384             6         10 jun 2021              17 jun 2022
29333       532             2         8 oct 2023               10 oct 2025

I have used a LAG function which works but not sure how I could amend this to skip the rows I don't need? My ideal output would look like this..

SPID        ID            Status       StartDate                 EndDate           PrevED
29333       102             7         01 jan 2013              1 Jan 2014        01-Jan-1900  
29333       202             6         7 Jun 2021               15 Jun 2022       1-Jan-2014
29333       384             6         10 jun 2021              17 jun 2022       1-Jan-2014
29333       532             2         8 oct 2023               10 oct 2025       1-Jan-2014

Any tips on the best way of achieving this?

CodePudding user response:

As I mentioned in the comments, LAG isn't well suited to this (unless you are on 2022). Instead, you'll likely want to use a derived table in the FROM:

SELECT YT.SPID,
       YT.ID,
       YT.Status,
       YT.StartDate,
       YT.EndDate,
       ISNULL(ED.EndDate,'19000101') AS PrevEdDate
FROM dbo.YourTable YT
     OUTER APPLY (SELECT TOP (1) oa.EndDate
                  FROM dbo.YourTable oa
                  WHERE oa.EndDate < YT.EndDate
                    AND oa.Status != 6
                  ORDER BY oa.EndDate DESC) ED;

If you were on 2022 (preview) then you could use LAG, and it's new utilise IGNORE NULLS feature alongside a CASE expression:

SELECT SPID,
       ID,
       Status,
       StartDate,
       EndDate,
       LAG(CASE WHEN Status != 6 THEN EndDate END,1,'19000101') IGNORE NULLS OVER (ORDER BY EndDate) AS PrevEd
FROM dbo.YourTable;

CodePudding user response:

You could do this:

lag(EndDate) over (order by iif(Status=6,1,0), EndDate)

It will sort by Status first, putting 6 at the bottom of the list, then use EndDate to find latest value with other status. Ofcourse, if there aren't any other previous statuses than 6, it'll still select it.

  • Related