Home > Software design >  Finding next node in T-SQL
Finding next node in T-SQL

Time:01-17

Suppose I have the following table (Date CustNum is an unique index)

RowId Date CustNum
1 1-Jan-2021 0001
2 1-Jan-2021 0002
3 1-Jan-2021 0004
4 2-Jan-2021 0001
5 3-Jan-2021 0001
6 3-Jan-2021 0004
7 7-Jan-2021 0004

The table has ~500K records.

What is the best method to get the previous and next rowid of the CustNum?

RowId Date CustNum CustPrevRowId CustNextRowId
1 1-Jan-2021 0001 4
2 1-Jan-2021 0002
3 1-Jan-2021 0004 6
4 2-Jan-2021 0001 1 5
5 3-Jan-2021 0001 4
6 3-Jan-2021 0004 3 7
7 7-Jan-2021 0004 6

I've tried to use sub-query but I have faced a performance issue.

SELECT T1.*,
    (SELECT TOP 1 RowID FROM T T2 WHERE T2.CustNum = T1.CustNum AND T2.Date < T1.Date ORDER BY DATE DESC) AS CustPrevRowId,
    (SELECT TOP 1 RowID FROM T T2 WHERE T2.CustNum = T1.CustNum AND T2.Date > T1.Date ORDER BY DATE ) AS CustNextRowId
 FROM T T1

CodePudding user response:

As already pointed in the comments, you can use the two window functions:

  • LAG, retrieves the previous row in the same partition, given a specified order
  • LEAD, does the same, but will get the following row instead

In this specific case, you want to:

  • partition on "CustNum" (since you want last row for each customer number)
  • order by the date field (so that it will attempt to get rowid with respect to last/next date)
SELECT *, LAG([RowId]) OVER(PARTITION BY [CustNum] ORDER BY [Date]) AS CustPrevRowId,
          LEAD([RowId]) OVER(PARTITION BY [CustNum] ORDER BY [Date]) AS CustNextRowId
FROM tab
ORDER BY RowId

Check the demo here.

Note: the last ORDER BY RowId clause is not necessary.

  • Related