Reputation: 7444
Say I have the following data:
Client Date Money
31CDAAFE-93BA-4666-AE6D-2253059990BB 2011-08-31 200000000.00
31CDAAFE-93BA-4666-AE6D-2253059990BB 2011-07-31 198000000.00
31CDAAFE-93BA-4666-AE6D-2253059990BB 2011-04-31 108000000.00
Is there an easy way to find the difference between the amounts (Money) for the latest and second latest record?
So for this data set the answer would be:
31CDAAFE-93BA-4666-AE6D-2253059990BB 2011-08-31 2000000.00
I basically need to return the 1st record with the client and date and the difference between the 2. Note there are multiple clients, dates and money and if there is only one date for a client I can just return the amount.
I've got as far as ranking the data but can't for the life of me figure out how to end up the result in one row...am I missing something obvious?
SELECT
Client,
Date,
Money,
ROW_NUMBER() OVER (PARTITION BY Client ORDER BY Date DESC) AS Sequence
FROM
MyTable
Upvotes: 1
Views: 96
Reputation: 58491
You have most of the work done.
All that's left to do is to wrap your statement into a WITH statement, JOIN
with itself and retain all rows where Sequence = 1
.
Note that clients with only 1 record will not be shown. I assume that is the most logical thing to do. You should change the INNER JOIN
to a LEFT OUTER JOIN
if my assumption is wrong.
;WITH q AS (
SELECT
Client,
Date,
Money,
ROW_NUMBER() OVER (PARTITION BY Client ORDER BY Date DESC) AS Sequence
FROM
MyTable
)
SELECT q1.Client
, q1.Date
, q1.Money - q2.Money
FROM q q1
INNER JOIN q q2 ON q2.Client = q1.Client
AND q2.Sequence = q1.Sequence + 1
WHERE q1.Sequence = 1
As you indicate in comments that you should read up on using WITH
statements, in essence, the WITH
statement in the example
Note that in this example, there is no recursion involved (usually associated with WITH
statements)
SELECT q1.Client
, q1.Date
, q1.Money - q2.Money
FROM (
SELECT
Client,
Date,
Money,
ROW_NUMBER() OVER (PARTITION BY Client ORDER BY Date DESC) AS Sequence
FROM
MyTable
) q1
INNER JOIN (
SELECT
Client,
Date,
Money,
ROW_NUMBER() OVER (PARTITION BY Client ORDER BY Date DESC) AS Sequence
FROM
MyTable
) q2 ON q2.Client = q1.Client
AND q2.Sequence = q1.Sequence + 1
WHERE q1.Sequence = 1
Upvotes: 1
Reputation: 402
I would break it down into two embedded sub-queries: One to find the row with the maximum date, the other to find the row with the maximum date not equaling the date of the first query, the join those queries on 1=1 (since you're getting one row from each), then get the difference in the overall query.
Upvotes: 0
Reputation: 432672
;WITH aCTE AS
(
SELECT
Client, Date, Money,
ROW_NUMBER() OVER (PARTITION BY Client ORDER BY [Date] DESC) AS rn
FROM
MyTable
)
SELECT
T1.Client, T1.Money - ISNULL(T2.Money, 0)
FROM
aCTE T1
LEFT JOIN
aCTE T2 ON T1.Client = T2.Client AND T2.rn = 2
WHERE
T1.rn = 1
Note: this covers where there is no "previous" row
Upvotes: 3
Reputation: 70678
You can try this:
WITH CTE AS
(
SELECT
Client,
Date,
Money,
ROW_NUMBER() OVER (PARTITION BY Client ORDER BY Date DESC) AS Sequence
FROM MyTable
)
SELECT A.Client, A.[Money] - B.[Money] MoneyDifference
FROM (SELECT * FROM CTE WHERE Sequence = 1) A
INNER JOIN (SELECT * FROM CTE WHERE Sequence = 2) B
ON A.Client = B.Client
Upvotes: 1