无法找出 plsql 过程中的循环游标
Can't figure out cursor for loop in a plsql procedure
我正在尝试在 plsql 中编写一个过程,它接受两个参数,month 和 year。该过程为 table - loanreport 生成数据。该过程为贷款类型 table 中的所有贷款类型生成。当程序是 运行 时,它应该用以下内容填充 table:
- 月
- 年
已关闭的贷款金额(状态为6的贷款的贷款金额之和)如果没有贷款的状态为6则已关闭的贷款金额为0。
4.平均收盘周期
以下是相关的 table:
CREATE TABLE LOANDETAILS
(LOANNO VARCHAR2(11) primary key,
PROPERTYID VARCHAR2(10),
CUSTID CHAR(8),
LOANTYPE VARCHAR2(20),
LOANSTATUSCODE NUMBER(3,0),
LOANAMOUNT NUMBER(10,2),
RATE NUMBER(5,2),
LOANCREATIONDATE DATE,
LOANSTATUSDATE DATE,
constraint loandet_prop_fk foreign key(PROPERTYID) references PROPERTIES(propertyid),
constraint loandet_cust_fk foreign key(CUSTID) references customers(custid),
constraint loandet_lt_fk foreign key (LOANTYPE) references loantypes(loantype)
);
--insert
Insert into LOANDETAILS values ('L1000000001','P1000001','C1000001','Conventional',1,87975,9,to_date('26-JUL-2016','DD-MON-YY'),to_date('02-AUG-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000009','P1000009','C1000009','FHA',6,160055,4.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000010','P1000010','C1000010','VA',2,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
CREATE TABLE LOANTYPES
(ltID char(5) constraint loantypes_pk primary key,
loantype VARCHAR2(20) constraint loantypes_lt_unique UNIQUE,
description VARCHAR2(100),
active char(1) constraint loantypes_active CHECK (active IN ('Y','N')) -- if loan type is currently being offered
);
Insert into loantypes values ('LT001', 'VA', 'Service members, veterans or eligible family','Y');
Insert into loantypes values ('LT002', 'FHA', 'Federal Housing Administration eligible loans', 'Y');
Insert into loantypes values ('LT003', 'Conventional', 'Standard loan','Y');
Insert into loantypes values ('LT004', 'Employee', 'Eligible employees of the organization','Y');
Insert into loantypes values ('LT005', 'Reconstruct', 'Relief work reconstruction','N');
CREATE TABLE LOANTYPEREPORT
(LOANTYPE VARCHAR2(20),
MONTH number(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2),
constraint loantr_pk PRIMARY KEY (LOANTYPE, RMONTH, RYEAR)
);
我是 sql 的新手,我显然有一些知识空白。我正在尝试创建一个过程,然后想创建一个游标并使用 for 循环遍历游标以创建所需的报告。这是我的不完整代码:
CREATE OR REPLACE PROCEDURE loan_type_report_procedure (Month loantypereport.month%type, Year loantypereport.year%type) AS
CURSOR C1 IS
SELECT l.loantype,
loanamount,
loancreationdate,
loanstatusdate,
loanstatuscode,
to_char(LOANCREATIONDATE, 'mm') AS rMonth,
to_char(LOANCREATIONDATE, 'YYYY') AS rYEAR
FROM LOANTYPES l
JOIN LOANDETAILS d
ON l.loantype = d.loantype
WHERE Month = to_char(LOANCREATIONDATE, 'mm')
AND Year = to_char(LOANCREATIONDATE, 'YYYY')
BEGIN
FOR loan_rec in C1 LOOP
就我的理解而言,for 循环在游标中逐行进行。如果我想要一份最终的 table 贷款类型报告 ,其中包含贷款类型、月份、年份、关闭的贷款金额和平均关闭期限 - 我该如何实现?已关闭的贷款金额和平均关闭期限均在贷款类型分组中汇总。我会在游标 select 语句中使用 group by 和 having 吗?
感谢您的见解
如果我对你的问题的理解正确,你想按 LOANTYPE
汇总每个月的贷款数量,以及已关闭的贷款 (LOANSTATUSCODE = 6
),你想要 SUM
他们的金额并记录他们的贷款时间跨度 AVERAGE
。
从 LOANTYPEREPORT
的外观来看,您似乎计划在几天内完成此平均跨度。
为此,您不需要使用 PL/SQL。这可以用传统的 SQL 来完成。我只是猜测决定贷款期限的标准是什么,所以我将在下面概述一个例子,其中有几个变化。
在这个例子中,我需要稍微修改一下您的 table,因为它们引用了您的 post 中未包含的其他 table(我删除了 LOANDET_PROP_FK
和LOANDET_CUST_FK
).
创建您的示例 tables 后,创建 LOANTYPEREPORT
table(从您的示例稍作修改以进行编译):
CREATE TABLE LOANTYPEREPORT
(LOANTYPE VARCHAR2(20),
MONTH NUMBER(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2),
CONSTRAINT LOANTR_PK PRIMARY KEY (LOANTYPE, MONTH, YEAR)
);
此外,我为一些 FHA 和常规贷款添加了一些额外数据,以帮助区分下面示例中的 SUM
s 和持续时间。
Insert into LOANDETAILS values ('L1000000001','P1000001','C1000001','Conventional',1,87975,9,to_date('26-JUL-2016','DD-MON-YY'),to_date('02-AUG-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000009','P1000009','C1000009','FHA',6,160055,4.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000010','P1000010','C1000010','VA',2,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000011','P1000010','C1000010','VA',6,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000012','P1000010','C1000010','VA',6,111111,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('17-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000013','P1000010','C1000010','VA',2,222222,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000014','P1000010','C1000010','Conventional',6,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-JAN-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000015','P1000010','C1000010','Conventional',5,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-FEB-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000016','P1000010','C1000010','Conventional',4,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-MAR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000017','P1000010','C1000010','FHA',4,444444,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-APR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000018','P1000010','C1000010','FHA',6,200000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-APR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000019','P1000010','C1000010','FHA',6,300000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-MAY-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000020','P1000010','C1000010','FHA',6,300000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('22-MAY-2017','DD-MON-YYYY'));
然后,您可以加载报告 table。
示例 1 这假设只有已结束的贷款应该包含在平均贷款期限中,贷款期限在 LOANCREATIONDATE
和 LOANSTATUSDATE
之间,并且您只需要几个月的数据和实际关闭贷款的贷款类型。这意味着 2016 年 7 月将完全不包括在内,因为该月没有关闭贷款。
INSERT INTO LOANTYPEREPORT
SELECT
LOANDETAILS.LOANTYPE,
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS YEAR,
SUM(LOANDETAILS.LOANAMOUNT) AS CLOSED_LOAN_AMOUNT,
AVG(LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE) AS AVERAGE_LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6
GROUP BY
LOANDETAILS.LOANTYPE,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE),
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE);
然后看看它做了什么:
SELECT YEAR,MONTH,LOANTYPE,CLOSEDLOANSAMOUNT,AVERAGECLOSINGPERIOD
FROM LOANTYPEREPORT
ORDER BY YEAR, MONTH, LOANTYPE;
YEAR MONTH LOANTYPE CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
2016 12 FHA 160055 7
2016 12 VA 328711 12
2017 1 Conventional 333333 58
2017 4 FHA 200000 148
2017 5 FHA 600000 175.5
示例 2: 但是,如果您想包含给定贷款类型没有关闭贷款的月份的数据(我不确定,但这可能是第三个post) 中的项目,那么您需要枚举月份。
您可以通过多种方式执行此操作,但我将在此示例中包含一个额外的查询,用于设置 2016 - 2018 年的边界。
运行插入:
INSERT INTO LOANTYPEREPORT
WITH YEAR_MONTH AS(
SELECT THE_MONTH.MONTH_NUMBER,
THE_YEAR.YEAR_NUMBER
FROM
(SELECT LEVEL AS MONTH_NUMBER FROM DUAL CONNECT BY LEVEL < 13) THE_MONTH
CROSS JOIN
(SELECT YEAR_NUMBER FROM
(SELECT LEVEL AS YEAR_NUMBER FROM DUAL CONNECT BY LEVEL < 2019)
WHERE YEAR_NUMBER BETWEEN 2016 AND 2018) THE_YEAR
)
SELECT
LOANTYPES.LOANTYPE,
YEAR_MONTH.MONTH_NUMBER,
YEAR_MONTH.YEAR_NUMBER,
SUM(COALESCE(CLOSED_LOAN.LOANAMOUNT,0)) AS CLOSED_LOAN_AMOUNT,
AVG(CLOSED_LOAN.LOAN_DURATION) AS AVERAGE_LOAN_DURATION
FROM
YEAR_MONTH
CROSS JOIN LOANTYPES
LEFT OUTER JOIN (SELECT EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS YEAR,
LOANDETAILS.LOANTYPE,
LOANDETAILS.LOANAMOUNT,
LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE AS LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6) CLOSED_LOAN
ON YEAR_MONTH.YEAR_NUMBER = CLOSED_LOAN.YEAR
AND YEAR_MONTH.MONTH_NUMBER = CLOSED_LOAN.MONTH
AND LOANTYPES.LOANTYPE = CLOSED_LOAN.LOANTYPE
GROUP BY YEAR_NUMBER, MONTH_NUMBER, LOANTYPES.LOANTYPE
ORDER BY YEAR_NUMBER, MONTH_NUMBER, LOANTYPES.LOANTYPE;
并查看生成的数据:
YEAR MONTH LOANTYPE CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
2016 1 Conventional 0
2016 1 Employee 0
2016 1 FHA 0
2016 1 Reconstruct 0
2016 1 VA 0
2016 2 Conventional 0
...
...
...
2016 12 Conventional 0
2016 12 Employee 0
2016 12 FHA 160055 7
2016 12 Reconstruct 0
2016 12 VA 328711 12
2017 1 Conventional 333333 58
2017 1 Employee 0
2017 1 FHA 0
2017 4 FHA 200000 148
2017 4 Reconstruct 0
2017 4 VA 0
2017 5 Conventional 0
2017 5 Employee 0
2017 5 FHA 600000 175.5
2017 5 Reconstruct 0
2017 5 VA 0
2017 6 Conventional 0
2017 6 Employee 0
2017 6 FHA 0
通过这种方式,您可以获得每种类型每个月结清的贷款的结清金额总和,如果 none 已结清,则为零。
EDIT 以 returning 从函数为例。
重申一下,您不需要使用函数来进行此类报告。
但是如果你有使用函数的要求,这里有一个例子:
首先,创建您的 return 类型:
CREATE TYPE LOAN_TYPE_MONTH_REPORT IS OBJECT (
LOANTYPE VARCHAR2(20),
MONTH number(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2)
);
/
CREATE TYPE LOAN_TYPE_MONTH_REPORT_LIST IS TABLE OF LOAN_TYPE_MONTH_REPORT;
/
然后创建你的函数:
CREATE FUNCTION GET_LOAN_TYPE_REPORT_FOR_MONTH(P_YEAR IN NUMBER, P_MONTH IN NUMBER)
RETURN LOAN_TYPE_MONTH_REPORT_LIST
IS
V_MONTH_REPORT LOAN_TYPE_MONTH_REPORT_LIST;
BEGIN
SELECT
LOAN_TYPE_MONTH_REPORT(
THE_MONTH_YEAR.LOANTYPE,
THE_MONTH_YEAR.THE_MONTH,
THE_MONTH_YEAR.THE_YEAR,
COALESCE(CLOSED_LOAN_SUMMARY.CLOSED_LOAN_AMOUNT,0),
CLOSED_LOAN_SUMMARY.AVERAGE_LOAN_DURATION)
BULK COLLECT INTO V_MONTH_REPORT
FROM
(SELECT P_YEAR AS THE_YEAR, P_MONTH AS THE_MONTH, LOANTYPES.LOANTYPE FROM LOANTYPES) THE_MONTH_YEAR
LEFT OUTER JOIN
(SELECT
LOANDETAILS.LOANTYPE,
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS THE_MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS THE_YEAR,
SUM(LOANDETAILS.LOANAMOUNT) AS CLOSED_LOAN_AMOUNT,
AVG(LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE) AS AVERAGE_LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6
GROUP BY
LOANDETAILS.LOANTYPE,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE),
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE)) CLOSED_LOAN_SUMMARY
ON THE_MONTH_YEAR.THE_YEAR = CLOSED_LOAN_SUMMARY.THE_YEAR
AND THE_MONTH_YEAR.THE_MONTH = CLOSED_LOAN_SUMMARY.THE_MONTH
AND THE_MONTH_YEAR.LOANTYPE = CLOSED_LOAN_SUMMARY.LOANTYPE;
RETURN V_MONTH_REPORT;
END;
/
然后测试一下:
这是一个月有两种贷款类型的关闭:
SELECT * FROM TABLE(GET_LOAN_TYPE_REPORT_FOR_MONTH(2016,12));
LOANTYPE MONTH YEAR CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
Employee 12 2016 0
VA 12 2016 328711 12
Reconstruct 12 2016 0
FHA 12 2016 160055 7
Conventional 12 2016 0
或者只有一种贷款类型的一个月结束:
SELECT * FROM TABLE(GET_LOAN_TYPE_REPORT_FOR_MONTH(2017,01));
LOANTYPE MONTH YEAR CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
Employee 1 2017 0
Reconstruct 1 2017 0
FHA 1 2017 0
VA 1 2017 0
Conventional 1 2017 333333 58
我正在尝试在 plsql 中编写一个过程,它接受两个参数,month 和 year。该过程为 table - loanreport 生成数据。该过程为贷款类型 table 中的所有贷款类型生成。当程序是 运行 时,它应该用以下内容填充 table:
- 月
- 年
已关闭的贷款金额(状态为6的贷款的贷款金额之和)如果没有贷款的状态为6则已关闭的贷款金额为0。
4.平均收盘周期
以下是相关的 table:
CREATE TABLE LOANDETAILS
(LOANNO VARCHAR2(11) primary key,
PROPERTYID VARCHAR2(10),
CUSTID CHAR(8),
LOANTYPE VARCHAR2(20),
LOANSTATUSCODE NUMBER(3,0),
LOANAMOUNT NUMBER(10,2),
RATE NUMBER(5,2),
LOANCREATIONDATE DATE,
LOANSTATUSDATE DATE,
constraint loandet_prop_fk foreign key(PROPERTYID) references PROPERTIES(propertyid),
constraint loandet_cust_fk foreign key(CUSTID) references customers(custid),
constraint loandet_lt_fk foreign key (LOANTYPE) references loantypes(loantype)
);
--insert
Insert into LOANDETAILS values ('L1000000001','P1000001','C1000001','Conventional',1,87975,9,to_date('26-JUL-2016','DD-MON-YY'),to_date('02-AUG-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000009','P1000009','C1000009','FHA',6,160055,4.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000010','P1000010','C1000010','VA',2,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
CREATE TABLE LOANTYPES
(ltID char(5) constraint loantypes_pk primary key,
loantype VARCHAR2(20) constraint loantypes_lt_unique UNIQUE,
description VARCHAR2(100),
active char(1) constraint loantypes_active CHECK (active IN ('Y','N')) -- if loan type is currently being offered
);
Insert into loantypes values ('LT001', 'VA', 'Service members, veterans or eligible family','Y');
Insert into loantypes values ('LT002', 'FHA', 'Federal Housing Administration eligible loans', 'Y');
Insert into loantypes values ('LT003', 'Conventional', 'Standard loan','Y');
Insert into loantypes values ('LT004', 'Employee', 'Eligible employees of the organization','Y');
Insert into loantypes values ('LT005', 'Reconstruct', 'Relief work reconstruction','N');
CREATE TABLE LOANTYPEREPORT
(LOANTYPE VARCHAR2(20),
MONTH number(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2),
constraint loantr_pk PRIMARY KEY (LOANTYPE, RMONTH, RYEAR)
);
我是 sql 的新手,我显然有一些知识空白。我正在尝试创建一个过程,然后想创建一个游标并使用 for 循环遍历游标以创建所需的报告。这是我的不完整代码:
CREATE OR REPLACE PROCEDURE loan_type_report_procedure (Month loantypereport.month%type, Year loantypereport.year%type) AS
CURSOR C1 IS
SELECT l.loantype,
loanamount,
loancreationdate,
loanstatusdate,
loanstatuscode,
to_char(LOANCREATIONDATE, 'mm') AS rMonth,
to_char(LOANCREATIONDATE, 'YYYY') AS rYEAR
FROM LOANTYPES l
JOIN LOANDETAILS d
ON l.loantype = d.loantype
WHERE Month = to_char(LOANCREATIONDATE, 'mm')
AND Year = to_char(LOANCREATIONDATE, 'YYYY')
BEGIN
FOR loan_rec in C1 LOOP
就我的理解而言,for 循环在游标中逐行进行。如果我想要一份最终的 table 贷款类型报告 ,其中包含贷款类型、月份、年份、关闭的贷款金额和平均关闭期限 - 我该如何实现?已关闭的贷款金额和平均关闭期限均在贷款类型分组中汇总。我会在游标 select 语句中使用 group by 和 having 吗?
感谢您的见解
如果我对你的问题的理解正确,你想按 LOANTYPE
汇总每个月的贷款数量,以及已关闭的贷款 (LOANSTATUSCODE = 6
),你想要 SUM
他们的金额并记录他们的贷款时间跨度 AVERAGE
。
从 LOANTYPEREPORT
的外观来看,您似乎计划在几天内完成此平均跨度。
为此,您不需要使用 PL/SQL。这可以用传统的 SQL 来完成。我只是猜测决定贷款期限的标准是什么,所以我将在下面概述一个例子,其中有几个变化。
在这个例子中,我需要稍微修改一下您的 table,因为它们引用了您的 post 中未包含的其他 table(我删除了 LOANDET_PROP_FK
和LOANDET_CUST_FK
).
创建您的示例 tables 后,创建 LOANTYPEREPORT
table(从您的示例稍作修改以进行编译):
CREATE TABLE LOANTYPEREPORT
(LOANTYPE VARCHAR2(20),
MONTH NUMBER(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2),
CONSTRAINT LOANTR_PK PRIMARY KEY (LOANTYPE, MONTH, YEAR)
);
此外,我为一些 FHA 和常规贷款添加了一些额外数据,以帮助区分下面示例中的 SUM
s 和持续时间。
Insert into LOANDETAILS values ('L1000000001','P1000001','C1000001','Conventional',1,87975,9,to_date('26-JUL-2016','DD-MON-YY'),to_date('02-AUG-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000009','P1000009','C1000009','FHA',6,160055,4.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000010','P1000010','C1000010','VA',2,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000011','P1000010','C1000010','VA',6,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000012','P1000010','C1000010','VA',6,111111,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('17-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000013','P1000010','C1000010','VA',2,222222,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000014','P1000010','C1000010','Conventional',6,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-JAN-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000015','P1000010','C1000010','Conventional',5,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-FEB-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000016','P1000010','C1000010','Conventional',4,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-MAR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000017','P1000010','C1000010','FHA',4,444444,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-APR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000018','P1000010','C1000010','FHA',6,200000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-APR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000019','P1000010','C1000010','FHA',6,300000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-MAY-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000020','P1000010','C1000010','FHA',6,300000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('22-MAY-2017','DD-MON-YYYY'));
然后,您可以加载报告 table。
示例 1 这假设只有已结束的贷款应该包含在平均贷款期限中,贷款期限在 LOANCREATIONDATE
和 LOANSTATUSDATE
之间,并且您只需要几个月的数据和实际关闭贷款的贷款类型。这意味着 2016 年 7 月将完全不包括在内,因为该月没有关闭贷款。
INSERT INTO LOANTYPEREPORT
SELECT
LOANDETAILS.LOANTYPE,
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS YEAR,
SUM(LOANDETAILS.LOANAMOUNT) AS CLOSED_LOAN_AMOUNT,
AVG(LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE) AS AVERAGE_LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6
GROUP BY
LOANDETAILS.LOANTYPE,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE),
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE);
然后看看它做了什么:
SELECT YEAR,MONTH,LOANTYPE,CLOSEDLOANSAMOUNT,AVERAGECLOSINGPERIOD
FROM LOANTYPEREPORT
ORDER BY YEAR, MONTH, LOANTYPE;
YEAR MONTH LOANTYPE CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
2016 12 FHA 160055 7
2016 12 VA 328711 12
2017 1 Conventional 333333 58
2017 4 FHA 200000 148
2017 5 FHA 600000 175.5
示例 2: 但是,如果您想包含给定贷款类型没有关闭贷款的月份的数据(我不确定,但这可能是第三个post) 中的项目,那么您需要枚举月份。
您可以通过多种方式执行此操作,但我将在此示例中包含一个额外的查询,用于设置 2016 - 2018 年的边界。
运行插入:
INSERT INTO LOANTYPEREPORT
WITH YEAR_MONTH AS(
SELECT THE_MONTH.MONTH_NUMBER,
THE_YEAR.YEAR_NUMBER
FROM
(SELECT LEVEL AS MONTH_NUMBER FROM DUAL CONNECT BY LEVEL < 13) THE_MONTH
CROSS JOIN
(SELECT YEAR_NUMBER FROM
(SELECT LEVEL AS YEAR_NUMBER FROM DUAL CONNECT BY LEVEL < 2019)
WHERE YEAR_NUMBER BETWEEN 2016 AND 2018) THE_YEAR
)
SELECT
LOANTYPES.LOANTYPE,
YEAR_MONTH.MONTH_NUMBER,
YEAR_MONTH.YEAR_NUMBER,
SUM(COALESCE(CLOSED_LOAN.LOANAMOUNT,0)) AS CLOSED_LOAN_AMOUNT,
AVG(CLOSED_LOAN.LOAN_DURATION) AS AVERAGE_LOAN_DURATION
FROM
YEAR_MONTH
CROSS JOIN LOANTYPES
LEFT OUTER JOIN (SELECT EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS YEAR,
LOANDETAILS.LOANTYPE,
LOANDETAILS.LOANAMOUNT,
LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE AS LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6) CLOSED_LOAN
ON YEAR_MONTH.YEAR_NUMBER = CLOSED_LOAN.YEAR
AND YEAR_MONTH.MONTH_NUMBER = CLOSED_LOAN.MONTH
AND LOANTYPES.LOANTYPE = CLOSED_LOAN.LOANTYPE
GROUP BY YEAR_NUMBER, MONTH_NUMBER, LOANTYPES.LOANTYPE
ORDER BY YEAR_NUMBER, MONTH_NUMBER, LOANTYPES.LOANTYPE;
并查看生成的数据:
YEAR MONTH LOANTYPE CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
2016 1 Conventional 0
2016 1 Employee 0
2016 1 FHA 0
2016 1 Reconstruct 0
2016 1 VA 0
2016 2 Conventional 0
...
...
...
2016 12 Conventional 0
2016 12 Employee 0
2016 12 FHA 160055 7
2016 12 Reconstruct 0
2016 12 VA 328711 12
2017 1 Conventional 333333 58
2017 1 Employee 0
2017 1 FHA 0
2017 4 FHA 200000 148
2017 4 Reconstruct 0
2017 4 VA 0
2017 5 Conventional 0
2017 5 Employee 0
2017 5 FHA 600000 175.5
2017 5 Reconstruct 0
2017 5 VA 0
2017 6 Conventional 0
2017 6 Employee 0
2017 6 FHA 0
通过这种方式,您可以获得每种类型每个月结清的贷款的结清金额总和,如果 none 已结清,则为零。
EDIT 以 returning 从函数为例。
重申一下,您不需要使用函数来进行此类报告。
但是如果你有使用函数的要求,这里有一个例子:
首先,创建您的 return 类型:
CREATE TYPE LOAN_TYPE_MONTH_REPORT IS OBJECT (
LOANTYPE VARCHAR2(20),
MONTH number(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2)
);
/
CREATE TYPE LOAN_TYPE_MONTH_REPORT_LIST IS TABLE OF LOAN_TYPE_MONTH_REPORT;
/
然后创建你的函数:
CREATE FUNCTION GET_LOAN_TYPE_REPORT_FOR_MONTH(P_YEAR IN NUMBER, P_MONTH IN NUMBER)
RETURN LOAN_TYPE_MONTH_REPORT_LIST
IS
V_MONTH_REPORT LOAN_TYPE_MONTH_REPORT_LIST;
BEGIN
SELECT
LOAN_TYPE_MONTH_REPORT(
THE_MONTH_YEAR.LOANTYPE,
THE_MONTH_YEAR.THE_MONTH,
THE_MONTH_YEAR.THE_YEAR,
COALESCE(CLOSED_LOAN_SUMMARY.CLOSED_LOAN_AMOUNT,0),
CLOSED_LOAN_SUMMARY.AVERAGE_LOAN_DURATION)
BULK COLLECT INTO V_MONTH_REPORT
FROM
(SELECT P_YEAR AS THE_YEAR, P_MONTH AS THE_MONTH, LOANTYPES.LOANTYPE FROM LOANTYPES) THE_MONTH_YEAR
LEFT OUTER JOIN
(SELECT
LOANDETAILS.LOANTYPE,
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS THE_MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS THE_YEAR,
SUM(LOANDETAILS.LOANAMOUNT) AS CLOSED_LOAN_AMOUNT,
AVG(LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE) AS AVERAGE_LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6
GROUP BY
LOANDETAILS.LOANTYPE,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE),
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE)) CLOSED_LOAN_SUMMARY
ON THE_MONTH_YEAR.THE_YEAR = CLOSED_LOAN_SUMMARY.THE_YEAR
AND THE_MONTH_YEAR.THE_MONTH = CLOSED_LOAN_SUMMARY.THE_MONTH
AND THE_MONTH_YEAR.LOANTYPE = CLOSED_LOAN_SUMMARY.LOANTYPE;
RETURN V_MONTH_REPORT;
END;
/
然后测试一下: 这是一个月有两种贷款类型的关闭:
SELECT * FROM TABLE(GET_LOAN_TYPE_REPORT_FOR_MONTH(2016,12));
LOANTYPE MONTH YEAR CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
Employee 12 2016 0
VA 12 2016 328711 12
Reconstruct 12 2016 0
FHA 12 2016 160055 7
Conventional 12 2016 0
或者只有一种贷款类型的一个月结束:
SELECT * FROM TABLE(GET_LOAN_TYPE_REPORT_FOR_MONTH(2017,01));
LOANTYPE MONTH YEAR CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
Employee 1 2017 0
Reconstruct 1 2017 0
FHA 1 2017 0
VA 1 2017 0
Conventional 1 2017 333333 58