Are you tired of doing self joins, just to get the value of a column in the
previus/subsequent row, or maybe even
smiling.
performance than self JOIN.
(
yearid int,
Monthid
int,
Profit bigint
)
SQL 2008 R2)
Profit)
VALUES
(2010,1,1766), (2010,2,100), (2010,3,1500), (2010,4,15000),
(2010,5,900), (2010,6,45),
(2010,7,1766), (2010,8,9100), (2010,9,-100),
(2010,10,50), (2010,11,900000), (2010,12,6575)
Yearid, MonthId, ProfitThisMonth and ProfitLastMonth, so that we would be able
to compare profit with last month. Before SQL Server Denali CTP3 my SQL
t1.yearid,
t1.Monthid,
t1.Profit as
ProfitThisMonth,
t2.Profit as ProfitLastMonth
FROM MonthlyProfit as
t1
LEFT JOIN MonthlyProfit as t2 on (t1.yearid = t2.yearid) AND (t1.Monthid =
t2.Monthid+1)
the nasty self join.
SQL Server Denali CTP3 finally gives us LAG and
LEAD. Here is the description directly stolen from BOL:
Accesses data
from a previous row in the same result set without the use of a self-join in
Microsoft SQL Server
access to a row at a given physical
SELECT statement to compare values in the
The syntax for LAG and
LEAD is the same
LAG (scalar_expression [,offset] [,default]) OVER ( [
partition_by_clause ] order_by_clause)
Let’s have a look at the
statement now:
yearid,
monthid,
Profit as
ProfitThisMonth,
LAG(Profit, 1, 0) OVER(Order by yearid, monthid) as
ProfitLastMonth
FROM MonthlyProfit
No more self joins, and a much more simple statement. Read the full
documentation to the LAG and LEAD in BOL.
What about performance?
I set IO statistics on(SET STATISTICS IO
ON;) and run both queries again. Here is the results:
(12 row(s)
affected)
Table 'MonthlyProfit'. Scan count 2, logical reads 13, physical
reads 0, read-ahead reads 0,…
(12 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0,
physical reads 0, read-ahead reads 0,…
Table 'MonthlyProfit'. Scan count 1,
logical reads 1, physical reads 0, read-ahead reads 0,
So the conclusion is,
we get a much simpler query that also does fewer reads, that’s what we call a
WIN-WIN situation.