Reputation: 185
I have tables Member
and Transaction
. Table Member
has 2 columns MemberID
and MemberName
. Table Transaction
has 3 columns, MemberID
, TransactionDate
, and MemberBalance
.
The rows in the tables are as shown below:
Table Member
:
MemberID MemberName
=============================
1 John
2 Betty
3 Lisa
Table Transaction
:
MemberID TransactionDate MemberBalance
=====================================================
1 13-12-2012 200
2 12-12-2012 90
1 10-09-2012 300
I would like to query for MemberID, MemberName
and MemberBalance
where the TransactionDate
is the latest (max) for each MemberID
.
My query is like this:
SELECT
t.MemberID, m.MemberName , t.MemberBalance
FROM
Member AS m
INNER JOIN
Transaction AS t ON m.MemberID = t.MemberID
WHERE
t.TransactionDate IN (SELECT MAX(TransactionDate)
FROM Transaction
GROUP BY MemberID)
This query returns:
MemberID MemberName MemberBalance
===================================================
1 John 200
2 Betty 90
My problem is, I want the query to return:
MemberID MemberName MemberBalance
===================================================
1 John 200
2 Betty 90
3 Lisa NULL
I want the member to be displayed even if its MemberID
does not exist in the Transaction
table.
How do I do this?
Thank you.
Upvotes: 1
Views: 120
Reputation: 184
SELECT a.MemberId,a.MemberName,a.MemberBalance
FROM
(
SELECT m.MemberId,m.MemberName,t1.MemberBalance
,ROW_NUMBER() OVER(PARTITION BY m.MemberId ORDER BY t1.TransactionDate DESC) AS RN
FROM
@Member m OUTER APPLY (SELECT t.MemberId,t.MemberBalance,t.TransactionDate
FROM @Transaction t WHERE m.MemberId=t.MemberId) t1
)a
WHERE a.RN=1
Upvotes: 0
Reputation: 3866
You need to use LEFT JOIN
. Also you had an error in your query because if two members had transactions at the same time you can get two rows for both the users.
Try this
SELECT t.MemberID, m.MemberName , t.MemberBalance
FROM Member AS m
LEFT JOIN Transaction AS t ON m.MemberID = t.MemberID AND t.TransactionDate=
(
SELECT MAX(TransactionDate)
FROM Transaction T2
WHERE T2.MemberID=t.MemberID
)
Upvotes: 1
Reputation: 2483
To keep member in the result set, you need an outer join.
Also, please don't forget to add a condition on memberid for inner select query, as you might get issues when a maximum date for one user would match a non-maximum date of another (your where condition would pass twice for the second user as his transaction dates would appear on the select's results twice, one would be his actual maximum date and another - the max date of some user matching a non-max date)
Upvotes: 2
Reputation: 247720
You can also use something like this:
SELECT m.MemberID, m.MemberName, t1.MemberBalance
FROM Member AS m
LEFT JOIN
(
select max(transactionDate) transactionDate,
MemberID
from Transactions
group by MemberID
) AS t
ON m.MemberID = t.MemberID
left join transactions t1
on t.transactionDate = t1.transactionDate
and t.memberid = t1.memberid
Upvotes: 5
Reputation: 107736
member to be displayed even if its MemberID does not exist in Transaction table
You can preserve rows using LEFT JOIN on the Member table to Transaction table.
where the TransactionDate is the latest (max) for each MemberID.
From SQL Server 2005 onwards, the preferred and better performing method is to use ROW_NUMBER()
SELECT MemberID, MemberName, MemberBalance
FROM (
SELECT m.MemberID, m.MemberName , t.MemberBalance,
row_number() over (partition by m.MemberID order by t.TransactionDate desc) rn
FROM Member AS m
LEFT JOIN [Transaction] AS t ON m.MemberID = t.MemberID
) X
WHERE rn=1;
Upvotes: 2