我多年来一直在编写SQL查询,但我仍然坚持这一点。
我在MySQL中有两个表:
LoanPaymentsDueId
,LoanId
,AmtDue
,DueDate
LoanPaymentsId
,LoanId
,AmtPaid
,PaidDate
表格之间的关系是LoanId
,而不是到期的具体付款。在一个完美的世界中DueDate = PaidDate
和AmtDue = AmtPaid
。但是,对我来说这复杂的是LoanPaymentsDueId
和LoanPaymentsId
之间的关系。该关系仅存在于LoanId
,允许在单个LOANPAYMENTSDUE付款上进行部分付款。
我研究过网络试图找到正确的查询创建一个显示每个LOANPAYMENTSDUE满足日期的报告。这需要计算LOANPAYMENTSDUE.DueDate的余额,因为可以有付款错过,新付款应满足最早的LOANPAYMENTSDUE付款余额。
以下是示例数据和表脚本:
CREATE TABLE LOANPAYMENTSDUE (
LoanPaymentsDueId BIGINT(20) NOT NULL AUTO_INCREMENT
, LoanId BIGINT(20)
, AmtDue double NOT NULL
, DueDate date NOT NULL
, PRIMARY KEY (LoanPaymentsDueId)
);
INSERT INTO LOANPAYMENTSDUE (LoanId, AmtDue, DueDate) VALUES (1, 100, '2013-07-15');
INSERT INTO LOANPAYMENTSDUE (LoanId, AmtDue, DueDate) VALUES (1, 100, '2013-08-15');
INSERT INTO LOANPAYMENTSDUE (LoanId, AmtDue, DueDate) VALUES (1, 100, '2013-09-15');
INSERT INTO LOANPAYMENTSDUE (LoanId, AmtDue, DueDate) VALUES (1, 100, '2013-10-15');
INSERT INTO LOANPAYMENTSDUE (LoanId, AmtDue, DueDate) VALUES (1, 100, '2013-11-15');
CREATE TABLE LOANPAYMENTS (
LoanPaymentsId BIGINT(20) NOT NULL AUTO_INCREMENT
, LoanId BIGINT(20)
, AmtPaid double NOT NULL
, PaidDate date NOT NULL
, PRIMARY KEY (LoanPaymentsId)
);
INSERT INTO LOANPAYMENTS (LoanId, AmtPaid, PaidDate) VALUES (1, 100, '2013-07-15'); /* Full pmt on due date */
INSERT INTO LOANPAYMENTS (LoanId, AmtPaid, PaidDate) VALUES (1, 100, '2013-08-10'); /* Full pmt a few days early */
INSERT INTO LOANPAYMENTS (LoanId, AmtPaid, PaidDate) VALUES (1, 100, '2013-09-22'); /* Full pmt a week late */
INSERT INTO LOANPAYMENTS (LoanId, AmtPaid, PaidDate) VALUES (1, 50, '2013-10-18'); /* Partial pmt a few days late */
INSERT INTO LOANPAYMENTS (LoanId, AmtPaid, PaidDate) VALUES (1, 50, '2013-11-07');/* Partial pmt 3 weeks late and satisfies the 10/15/2013 balance on this date */
INSERT INTO LOANPAYMENTS (LoanId, AmtPaid, PaidDate) VALUES (1, 100, '2013-11-22');/* Full pmt a week late and satisfies the 11/15/2013 pmt due */
报告查询应该只在满足每个LOANPAYMENTSDUE时提供PAIDDATE。使用报告上方的表格数据如下:
LOANID LOANPAYMENTSDUEID AMTDUE DUEDATE PAIDDATE
1 1 100 2013-07-15 2013-07-15
1 2 100 2013-08-15 2013-08-10
1 3 100 2013-09-15 2013-09-22
1 4 100 2013-10-15 2013-11-07
1 5 100 2013-11-15 2013-11-22
答案 0 :(得分:0)
您可以从这两个查询开始,这两个查询返回具有正在运行的总列的所有行:
SELECT
LoanId, DueDate,
CASE WHEN LoanId=@last_LoanId THEN @Due:=@Due+AmtDue
ELSE @Due:=AmtDue END total_due,
@last_LoanId:=LoanId
FROM
LOANPAYMENTSDUE, (SELECT @last_LoanId:=NULL, @Due:=NULL) t;
SELECT
LoanId, PaidDate,
CASE WHEN LoanId=@last_LoanId THEN @Paid:=@Paid+AmtPaid
ELSE @Paid:=AmtPaid END total_paid,
@last_LoanId:=LoanId
FROM
LOANPAYMENTS, (SELECT @last_LoanId:=NULL, @Paid:=NULL) t;
然后你可以在due.LoanId = due.LoanId和total_due< = total_paid上使用LEFT JOIN,并使用GROUP BY获得连接成功的最小日期:
SELECT
ld.LoanId, ld.DueDate, MIN(lp.PaidDate)
FROM
(SELECT
LoanId, DueDate,
CASE WHEN LoanId=@last_LoanId1 THEN @Due:=@Due+AmtDue ELSE @Due:=AmtDue END total_due,
@last_LoanId1:=LoanId
FROM
LOANPAYMENTSDUE, (SELECT @last_LoanId1:=NULL, @Due:=NULL) t1) ld
LEFT JOIN
(SELECT
LoanId, PaidDate,
CASE WHEN LoanId=@last_LoanId2 THEN @Paid:=@Paid+AmtPaid ELSE @Paid:=AmtPaid END total_paid,
@last_LoanId2:=LoanId
FROM
LOANPAYMENTS, (SELECT @last_LoanId2:=NULL, @Paid:=NULL) t2) lp
ON
ld.LoanId=lp.LoanId AND ld.total_due<=lp.total_paid
GROUP BY
ld.LoanId, ld.DueDate
请参阅小提琴here。
答案 1 :(得分:0)
假设当支付金额时,它的支付部分或剩余金额全部支付,您可以根据总金额和支付的总金额进行检查。这是sqlFiddle example of your data and query
SELECT T1.LoanId,
T1.LoanPaymentsDueId,
T1.AmtDue,
T1.DueDate,
T2.PaidDate
FROM
(SELECT
LD.LoanPaymentsDueId,
LD.LoanId,
LD.DueDate,
LD.AmtDue,
(SELECT Sum(AmtDue)
FROM LOANPAYMENTSDUE LD1
WHERE LD1.DueDate <= LD.DueDate
AND LD1.LoanId = LD.LoanId
)as AmtDueTotal
FROM
LOANPAYMENTSDUE LD
)T1,
(SELECT
L.LoanPaymentsId,
L.LoanId,
L.PaidDate,
(SELECT Sum(AmtPaid)
FROM LOANPAYMENTS L1
WHERE L1.PaidDate <= L.PaidDate
AND L1.LoanId = L.LoanId
)as AmtPaidTotal
FROM LOANPAYMENTS L
)T2
WHERE
T1.LoanId = T2.LoanId
AND T1.LoanId = 1
AND T1.AmtDueTotal = T2.AmtPaidTotal;