Puoi usare la funzione ROW_NUMBER() qui:
SELECT *
FROM (SELECT lp.ID, lp.LoanID, lp.PaymentDate
, ROW_NUMBER() OVER (PARTITION BY YEAR(PaymentDate), Month(PaymentDate) ORDER BY PaymentDate DESC) 'RowRank'
FROM LoanPayments lp
)sub
WHERE RowRank = 1
Questo è solo il PaymentDate più recente per ogni mese, se lo volessi tramite LoanID aggiungeresti LoanID al PARTITION BY
elenco. Se eri interessato a preservare i legami potresti usare RANK()
invece di ROW_NUMBER()