问题
I am building a query in Microsoft sql server where I want to find the active loans as well as some information on them. I have built out a common table expression that gives me the correct population. Now I need to get the last 6 payments starting from today. I have a another common table expression that gives all the payments and the payment data received but I am not sure how to pivot and append the last 6 payments such that I have something like this:
This is what the query and output looks like for the common table expression where I can get c1,...,c6.
SELECT Account,Total,CONVERT(datetime,DateRec) [Date Received]
FROM mars.dbo.vw_PaymentHistory PH
WHERE PH.SourceTyp not like '%fundin%' and PH.SourceTyp not like '%draw%'
which gives this (but much more):
Here is the whole query I am working from:
Declare @monthEnding date = '3/31/2020',
@monthStart date = '3/1/2020';
WITH Active_Loans as (
SELECT
la.Account,
la.LoanStatus,
la.PrinBal,
isnull(b.Amount, 0) [DUPB],
la.PrinBal + isnull(b.Amount, 0) [TotalUPB],
l.NoteOwner,
pt.[Partition],
l.paidoffdate,
la.[First Name],
la.[Last Name],
la.PmtPI,
la.PmtImpound,
la.NextDueDate,
la.MaturityDate,
la.NoteOwner as [Note Owner]
FROM MARS_DW..vw_vw_Loans_ArchiveEOM la
LEFT JOIN MARS_DW..vw_DUPBByLoan b on b.Account = la.Account
AND b.ArchiveDate = la.ArchiveDate
LEFT JOIN MARS..vw_Loans l on l.Account = la.Account
LEFT JOIN Portfolio_Analytics..partition_table pt on pt.Noteowner = l.NoteOwner
WHERE la.MonthEnding = @monthEnding
AND la.isActive = 1
AND la.PaidOffDate is null
AND la.LoanStatus NOT LIKE 'BK Payment Plan'
AND la.LoanStatus NOT LIKE 'Prelim'
AND la.LoanStatus NOT like 'trailing claims'
AND la.Account NOT IN (
SELECT account
FROM MARS..vw_Loans
WHERE servicexferdate <=
DATEADD(dd, - 1, DATEADD(mm, DATEDIFF(mm, 0, @monthStart) + 1, 0))
AND PaidOffDate BETWEEN @monthStart AND DATEADD(dd, - 1, DATEADD(mm, DATEDIFF(mm, 0, @monthStart) + 1, 0))
)
UNION
(
SELECT l.account
,la.LoanStatus
,la.PrinBal
,isnull(b.Amount, 0) [DUPB]
,la.PrinBal + isnull(b.Amount, 0) [TotalUPB]
,l.NoteOwner
,pt.[Partition]
,l.PaidOffDate
,la.[First Name]
,la.[Last Name]
,la.PmtPI
,la.PmtImpound
,la.NextDueDate
,la.MaturityDate
,la.NoteOwner as [Note Owner]
FROM MARS..vw_Loans l
LEFT JOIN MARS_DW..vw_vw_Loans_ArchiveEOM la on la.Account = l.Account
LEFT JOIN MARS_DW..vw_DUPBByLoan b on b.Account = la.Account
LEFT JOIN Portfolio_Analytics..partition_table pt on pt.Noteowner = l.NoteOwner
AND b.ArchiveDate = la.ArchiveDate
WHERE l.servicexferdate < @monthEnding
AND l.PaidOffDate > @monthEnding
AND la.MonthEnding = @monthEnding
AND la.LoanStatus NOT like 'trailing claims'
AND la.LoanStatus NOT like 'Inactive - REO/FC'
AND pt.[Partition] IS NOT NULL
)
)
,
payments as
(
SELECT Account,Total,CONVERT(datetime,DateRec) [Date Received]
FROM mars.dbo.vw_PaymentHistory PH
WHERE PH.SourceTyp not like '%fundin%' and PH.SourceTyp not like '%draw%'
)
SELECT
rptpop.Account
, rptpop.[First Name]
, rptpop.[Last Name]
, '$' + CONVERT (VARCHAR (12), rptpop.PmtPI+rptpop.PmtImpound, 1) as PITI
,'$' + CONVERT (VARCHAR (12), rptpop.TotalUPB, 1) as [Total UPB]
, CONVERT(VARCHAR(10),rptpop.NextDueDate,101) as [Next Due Date]
, CONVERT(VARCHAR(10),rptpop.MaturityDate,101) as [Maturity Date]
, rptpop.[Note Owner]
FROM Active_Loans as rptpop
LEFT JOIN payments as pmt on pmt.Account = rptpop.Account
WHERE
rptpop.Partition = 'GAEA'
AND rptpop.LoanStatus = 'Current'
AND rptpop.[Last Name] NOT LIKE '%CRE%'
AND pmt.[Date Received] BETWEEN @monthStart AND @monthEnding
EDIT:
Based on the answer below I was able to do this:
payments as
(
SELECT ROW_NUMBER() OVER(Partition By Account ORDER BY CONVERT(datetime,DateRec) DESC) AS [RowNumber], Total, Account
FROM mars.dbo.vw_PaymentHistory
)
,
get_payment1 as
(
SELECT * FROM payments
where RowNumber = 1
)
Which gives me numbers but what I do not understand is whether 1.) This is indeed correct and 2.) Assuming it is correct how do is it getting the most recent date? Perhaps its the order by clause?
回答1:
I see a couple of way to solve the problem. I can share the approach using pseudo code.
Create Payments CTE , something like SELECT ROW_NUMBER() OVER(Partition By Account ORDER BY ReceivedDate DESC)
. Then create 6 CTE's that use the above CTE with Row_Number 1 thru 6. Then simply use those using Left Join in your query, joining on Account#. This will add c1-c6 columns.
A second approach can be to use the same Payments CTE but instead of multiple CTEs, find a way to use UNPIVOT unpivot (Amount for Rows in (1,2,3,4,5,6) ) u;
来源:https://stackoverflow.com/questions/61781399/pivoting-to-append-the-last-6-payments-for-24-loans