Reputation:
I'm looking for the following
TBL_TRANSACTION
(
ACCOUNT ID
TRANSACTION_DETAILS
TRANSACTION_DATE
TRANSACTION_TYPE
)
ACC_ID TRANS_DTLS TRANS_DATE TRANS_TYPE
1001 Petrol 01-Sept-2015 Cash
1001 Petrol 01-July-2015 Cash
1001 Fruit 01-May-2015 Cash
1001 Biscuits 01-Feb-2015 Cash
1002 Cereal 01-Sept-2015 Cash
1002 Soft Drinks 01-July-2015 Card
1002 Water 01-May-2015 Cash
1002 Water 01-Feb-2015 Card
1003 Milk 01-Sept-2015 Card
1003 Petrol 01-July-2015 Cash
1003 Cereal 01-May-2015 Cash
1003 Biscuits 01-Feb-2015 Cash
Basically, I want to be able to pull back the records of the account IF the last 3 transactions have ALL been paid for by Cash.
Regarding the data above, Account 1001 would be returned as the last 3 transactions have all been Cash, where are 1002 and 1003 would not as at least 1 of the last 3 transactions are card payments.
Upvotes: 1
Views: 225
Reputation: 45096
with cte as
( select ACCOUNT_ID
, TRANSACTION_DETAILS
, TRANSACTION_DATE
, TRANSACTION_TYPE
, row_number() over (partition by ACCOUNT_ID order by TRANSACTION_DATE desc) as rn
from TBL_TRANSACTION
)
select cm.*
from cte cm
where cm.rn <= 3
-- and cm.TRANSACTION_TYPE = 'cash'
and cm.ACCOUNT_ID not in ( select cx.ACCOUNT_ID
from cte cx
where rn <= 3
and TRANSACTION_TYPE <> 'cash' )
Upvotes: 0
Reputation: 1270021
You can get the last three accounts using row_number()
. You can get the last three cash account using row_number()
as well, with a different partitioning clause. If the values are the same for the first three, then the last three are cash.
select t.*
from (select t.*,
sum(case when seqnum = seqnum_type then 1 else 0 end) over (partition by acc_id) as num_in_sequence
from (select t.*,
row_number() over (partition by acc_id order by transaction_date desc) as seqnum,
row_number() over (partition by acc_id, trans_type order by transaction_date desc) as seqnum_type
from tbl_transaction t
) t
where trans_type = 'cash'
)
where num_in_sequence >= 3 and seqnum <= 3;
Another method compares the transaction types for the last three records:
select t.*
from (select t.*,
min(trans_type) over (partition by acc_d) as min_trans_type,
max(trans_type) over (partition by acc_d) as max_trans_type
from (select t.*,
row_number() over (partition by acc_id order by transaction_date desc) as seqnum
from tbl_transaction t
) t
where seqnum <= 3
)
where min_trans_type = 'cash' and max_trans_type = 'cash';
Upvotes: 0
Reputation: 40481
You didn't tag your RDBMS, so for ANSI-SQL you can use ROW_NUMBER()
:
SELECT tr.* FROM tbl_transaction tr
INNER JOIN(
SELECT t.acc_id FROM (
SELECT t.acc_id,t.trans_type,
ROW_NUMBER() OVER(PARTITION BY t.acc_id ORDER BY t.trans_date DESC) as rnk
FROM tbl_transaction t) tt
WHERE tt.rnk < 4 and t.trans_type = 'Cash'
GROUP BY tt.acc_id having count(*) = 3) s
ON(t.acc_id = s.acc_id)
Upvotes: 1