This document provides a summary of SQL strategies, recommendations, and examples focused on querying the XP2 database at credit unions. It covers basic table joins, including left, right, inner, full outer joins and slightly more complex "twisted" joins using WHERE clauses. It also demonstrates multiple joins, using EXCEPT clauses to exclude records, querying across multiple databases, and techniques for displaying primary and secondary names for a loan on the same row. The document is intended to give readers a practical understanding of SQL for querying the XP2 database.
1. Simplified path to
Accurate Reporting
Practical understanding of Basic
SQL Strategies, recommendations
and cheat sheets
written in reference to the XP2
database at Credit Unions
2. Brief
Description
• This book will give you a pretty
practical understanding of SQL
queries
• This is written in regards to XP2
database at credit unions
• XP2 users at credit unions with zero to
no knowledge on writing SQL queries
will benefit the most, although this
book will benefit anyone else at other
financial institutions or organizations
looking to quickly grasp practical
knowledge in SQL
– Kartik Suvarna
4. Table Joins – Straight Forward
LEFT | LEFT OUTER JOIN
BA
Records common
between Table A and
Table B
+
The rest of the records
in Table A
A: Membership|B: SEG
You need a list of memberships and their SEGs regardless
of whether they are associated with a SEG
FROM DB2INST1.MEMBERSHIP M
LEFT JOIN DB2INST1.SEG S ON S.SEG_CODE = M.CURRENT_SEG_CODE
Even memberships w/o a SEG will be
displayed
Example
DB2INST1 is the Schema for XP2 users. Will differ for
others, but the rest of the concept can be duplicated.
Table Name Alias [Prevents you from retyping table
names]
5. Table Joins – Straight Forward
RIGHT | RIGHT OUTER JOIN
A
Records common
between Table A and
Table B
+
The rest of the records
in Table B
A: Prebookloan|B: Loan
If you need a list of applications #s that were booked only.
FROM DB2INST1.PREBOOKLOAN P
LEFT JOIN DB2INST1.LOAN L ON L.LOAN_NOTE_NBR = PB.APLNUM
Only Booked Loans will be displayed
B
Example
6. Table Joins – Straight Forward
JOIN | INNER JOIN
A
Records common
between Table A and
Table B
+
The rest of the records
in Table B
A: Prebookloan|B: Loan
If you need a list of applications #s that were booked only.
Same example as the last slide – One query can be written multiple different ways
FROM DB2INST1.PREBOOKLOAN P
JOIN DB2INST1.LOAN L ON L.LOAN_NOTE_NBR = PB.APLNUM
Only Booked Loans will be displayed
B
Example
7. Table Joins – Straight Forward
FULL OUTER JOIN
A
All Records in A & B –
inclusive and
exclusive of each other
A: LOAN|B: EXTERNALCREDITCARDPAYMENT
If you need all members with credit cards and all
members with loans regardless of whether or not they
have both or one of the two.
FROM DB2INST1.EXTERNALCREDITCARDPAYMENT EP
LEFT JOIN DB2INST1.LOAN L ON L.MEMBER_NBR = EP.MEMBER_NBR
Displays members w/ credit cards and
loans as well as members w/ either one
of the two
B
Example
Rarely used
9. Table Joins – Slightly Twisted
LEFT JOIN
A
Records in A that are
not part of B
A: MEMBERSHIP|B:
EXTERNALCREDITCARDPAYMENT
If you want to send out mailers to members that do not
have a credit card.
FROM DB2INST1.MEMBERSHIP M
LEFT JOIN DB2INST1.EXTERNALCREDITCARD EP ON EP.MEMBER_NBR =
M.MEMBER_NBR WHERE EP.MEMBER_NBR IS NULL
Displays members without a credit
card
B
Example
For many, the first approach would be to link to the
application and exclude the ones that qualified or got
approved for the credit cards.
Risk of making a mistake and excluding ones
that were approved but don’t have it anymore,
regardless – this is a straightforward accurate
approach.
10. Table Joins – Slightly Twisted
RIGHT JOIN
Records in B that are
not part of A
A: LOAN|B: EXTERNALCREDITCARDPAYMENT
If you want to send out mailers to members that have a
credit card but not loan.
FROM DB2INST1.LOAN L
RIGHT JOIN DB2INST1.EXTERNALCREDITCARD EP ON EP.MEMBER_NBR =
L.MEMBER_NBR WHERE L.MEMBER_NBR IS NULL
Displays members with a credit card
but without a loan
Example
BA
Same concept here as previous slide – This is
an accurate and straightforward alternative to
other potential ways.
11. Table Joins – Slightly Twisted
FULL OUTER JOIN
Records in A and
Records in B minus
common records
between A & B
A: LOAN|B: EXTERNALCREDITCARDPAYMENT
If you need a report of members with loans and members
with credit cards but not members that have both
products
FROM DB2INST1.LOAN L
RIGHT JOIN DB2INST1.EXTERNALCREDITCARD EP ON EP.MEMBER_NBR =
L.MEMBER_NBR WHERE (L.MEMBER_NBR IS NULL OR EP.MEMBER_NBR IS
NULL)
Displays members with a credit card
but without a loan
Example
BA
13. FROM DB2INST1.LOAN L
JOIN DB2INST1.MEMBERSHIP M ON M.MEMBER_NBR = L.MEMBER_NBR
JOIN DB2INST1.MEMBERSHIPPARTICIPANT MP ON MP.MEMBER_NBR =
L.MEMBER_NBR
LEFT OUTER JOIN DB2INST1.SEG S ON S.SEG_CODE =
M.CURRENT_AFFILIATION
JOIN DB2INST1.ACCOUNT A ON A.ACCOUNT_NBR = L.LOAN_NBR AND
A.MEMBER_NBR = L.MEMBER_NBR
A
C B
A: LOAN|B: MEMBERSHIP |
C:MEMBERSHIPPARTICIPANT | D:SEG | E:
ACCOUNT
D
E
If the CU is SEG based, there will be occasions when the
member didn’t come in through a SEG, which is why a Left
outer Join or a Left Join between B and D, helps display the
ones with a SEG and ones with SEG field as NULL
14. FROM DB2INST1.MEMBERSHIP M
JOIN DB2INST1.ACCOUNT A ON A.MEMBER_NBR = M.MEMBER_NBR
LEFT JOIN DB2INST1.SHARE S ON S.MEMBER_NBR = A.MEMBER_NBR AND
S.SHARE_NBR = A.ACCOUNT_NBR
LEFT JOIN DB2INST1.LOAN L ON L.MEMBER_NBR = A.MEMBER_NBR AND
L.LOAN_NBR = A.ACCOUNT_NBR
JOIN DB2INST1.AGR_MEMBERTOTAL AM ON AM.MEMBER_NBR =
M.MEMBER_NBR
A: MEMBERSHIP|B: ACCOUNT | C: SHARE | D:
LOAN | E: AGR_MEMBERTOTAL
B
Share and Loan in one Query? – Of course it’s possible
A DC
C & D have a left outer join with B, but B has only
an inner join with A.
Now, if A didn’t exist, then B would be colored all
blue – Just making more sense visually.
Currently, it looks
confusing, but w/o A it
would look way more
straightforward.
16. Except Clause: Exclude Members w/ certain product types
One would pull the Share Table and say WHERE
S.SHARE_TYPE <> 97
Why is this incorrect?
Incase a member has other accounts other than a share
type 97, those members will be displayed. The above
WHERE clause will not completely exclude those
members.
First Approach but incorrect approach:
Say you need to completely exclude members with Share
Types 97
The Right Approach: Use an ‘Except Clause’ ----
SELECT S.MEMBER_NBR
FROM DB2INST1.SHARE S
EXCEPT
SELECT S.MEMBER_NBR
FROM DB2INST1.SHARE S
WHERE S.SHARE_TYPE = 97
GROUP BY S.MEMBER_NBR
Notice that there are 2 SELECT
statements
The second SELECT statement says
exclude members with share type
97 completely.
While using the Except clause, both
the SELECT statements need to
have the same number of fields.
Next Page – A slightly complicated example of a
query with an Except Clause –
17. Except Clause: Exclude Members w/ certain product types
SELECT S.MEMBER_NBR, I.D1NAME, I.BIRTH_DATE, MP.PARTICIPATION_TYPE,
AM.SV_SD_CNT AS SHAREDRAFTCOUNT, OS.SRC_MBR_NBR AS
SOURCE_MEMBERNBR, OS.SRC_ACCT_NBR AS SOURCE_ACCTNBR,
E.EMAIL_ADDRESS
FROM DB2INST1.SHARE S
JOIN DB2INST1.AGR_MEMBERTOTAL AM ON AM.MEMBER_NBR = S.MEMBER_NBR
JOIN DB2INST1.MEMBERSHIPPARTICIPANT MP ON MP.MEMBER_NBR =
AM.MEMBER_NBR
JOIN DB2INST1.INDIVIDUAL I ON I.INDIVIDUAL_ID = MP.INDIVIDUAL_ID
LEFT JOIN DB2INST1.ODPSOURCE OS ON OS.MEMBER_NBR = S.MEMBER_NBR AND
OS.SHARE_NBR = S.SHARE_NBR
LEFT JOIN DB2INST1.EMAIL E ON E.INDIVIDUAL_ID = I.INDIVIDUAL_ID
WHERE S.SHARE_TYPE = 97 AND (S.CLOSED = 0 OR S.CLOSED IS NULL) AND
(AM.SV_SD_CNT > 1) AND (CAST((DAYS(CURRENT DATE) -
DAYS(I.BIRTH_DATE))/365.25 as INTEGER) >= 18)
EXCEPT
SELECT S.MEMBER_NBR, I.D1NAME, I.BIRTH_DATE, MP.PARTICIPATION_TYPE,
AM.SV_SD_CNT AS SHAREDARFTCOUNT, OS.SRC_MBR_NBR AS
SOURCE_MEMBERNBR, OS.SRC_ACCT_NBR AS SOURCE_ACCTNBR,
E.EMAIL_ADDRESS
FROM DB2INST1.SHARE S
JOIN DB2INST1.AGR_MEMBERTOTAL AM ON AM.MEMBER_NBR = S.MEMBER_NBR
JOIN DB2INST1.MEMBERSHIPPARTICIPANT MP ON MP.MEMBER_NBR =
AM.MEMBER_NBR
JOIN DB2INST1.INDIVIDUAL I ON I.INDIVIDUAL_ID = MP.INDIVIDUAL_ID
LEFT JOIN DB2INST1.ODPSOURCE OS ON OS.MEMBER_NBR = S.MEMBER_NBR AND
OS.SHARE_NBR = S.SHARE_NBR
LEFT JOIN DB2INST1.EMAIL E ON E.INDIVIDUAL_ID = I.INDIVIDUAL_ID
WHERE (S.SHARE_TYPE = 2 or S.SHARE_TYPE = 99 OR AM.SV_SD_CNT <= 1)
GROUP BY S.MEMBER_NBR, AM.SV_SD_CNT, I.D1NAME, I.BIRTH_DATE,
MP.PARTICIPATION_TYPE, OS.SRC_MBR_NBR, OS.SRC_ACCT_NBR,
E.EMAIL_ADDRESS
Members w/ more than one checking, one of them being a share type 97, but none
of them being a share type 2 or 99
18. Using multiple databases
Natural first approach – Match them on
excel via a common column.
Dataset Expert >> Create New Connection>>
OLE DB (ADO) >> Microsoft Office 12.0
Access Database Engine >> Select the source
file. Then join via common column
(Example – Member Number)
Efficient Approach:
First Approach:
Excel is one of the best tools, but can get
slow with too much data and formulas –
Hence, the more done within the SQL query,
the better for the end user looking at the
final product.
19. Having Primary/Secondary names in one row
SELECT L.MEMBER_NBR||'-'|| L.LOAN_NBR AS MEMBER_LOAN, L.MEMBER_NBR,
L.LOAN_NBR, L.OPEN_DATE, CV.VINSTR, CV.YEAR, CV.MAKE, CV.MODEL,
I.D1NAME AS BORROWER, A.ADDRESS1, A.ADDRESS2, A.CITY, A.STATE, A.ZIP_STR,
L.BALANCE, LP.XPTIMESTAMP, I.TIN ||'-'|| CV.VINSTR AS TIN_VIN,
LP.LOAN_PROPERTY_VALUE
FROM DB2INST1.LOAN L
LEFT OUTER JOIN DB2INST1.ACCOUNTINDIVIDUAL AI ON AI.MEMBER_NBR =
L.MEMBER_NBR AND AI.ACCOUNT_NBR = L.LOAN_NBR
JOIN DB2INST1.INDIVIDUAL I ON I.INDIVIDUAL_ID = AI.INDIVIDUAL_ID
LEFT OUTER JOIN DB2INST1.OWNERSHIPCATEGORY OC ON
OC.OWNERSHIP_CATEGORY_ID = AI.PARTICIPATION_TYPE
JOIN DB2INST1.OWNERSHIPCATEGORYCLASS OCC ON
OCC.OWNERSHIP_CATEGORY_ID = OC.OWNERSHIP_CATEGORY_ID
JOIN DB2INST1.LOANPROPERTY LP ON LP.MEMBER_NBR = L.MEMBER_NBR AND
LP.LOAN_NBR = L.LOAN_NBR
JOIN DB2INST1.LOANCOLLATERAL LC ON LC.MEMBER_NBR = LP.MEMBER_NBR
AND LC.LOAN_NBR = LP.LOAN_NBR
JOIN DB2INST1.COLLATERALVEHICLE CV ON CVDA.COLLATERAL_ID =
LC.COLLATERAL_ID
JOIN DB2INST1.MEMBERSHIP M ON M.MEMBER_NBR = AI.MEMBER_NBR
JOIN DB2INST1.MEMBERSHIPADDRESS MA ON MA.MEMBER_NBR =
M.MEMBER_NBR
LEFT OUTER JOIN DB2INST1.ADDRESS A ON A.ADDRESS_ID = MA.ADDRESS_ID
WHERE (OCC.OWNERSHIP_CLASS_ID = 1) AND (L.CLOSED = 0 OR L.CLOSED IS
NULL) and (MA.MEMBERSHIP_ADDRESS_TYPE = 1) AND (MA.INDEX = 1) AND
(LP.ITEM_NAME = 'OXVINTEKBOOKDATE') AND (OC.OWNERSHIP_CATEGORY_ID =
6)
GROUP BY L.MEMBER_NBR||'-'|| L.LOAN_NBR, L.MEMBER_NBR, L.LOAN_NBR,
L.OPEN_DATE, CV.VINSTR, CV.YEAR, CV.MAKE, CV.MODEL, I.D1NAME, A.ADDRESS1,
A.ADDRESS2, A.CITY, A.STATE, A.ZIP_STR, L.BALANCE, LP.XPTIMESTAMP, I.TIN ||'-
'|| CV.VINSTR, LP.LOAN_PROPERTY_VALUE
It is a 2 step process, to have the borrower and co-borrower associated with one
loan to display in one row. Two queries need to be written:
Query 1: The WHERE clause is only looking at Primary members or borrowers.
20. Having Primary/Secondary names in one row – Cont…
SELECT L.MEMBER_NBR||'-'|| L.LOAN_NBR AS MEMBER_LOAN, L.MEMBER_NBR,
L.LOAN_NBR, L.OPEN_DATE, OC.OWNERSHIP_CATEGORY_ID, CV.VINSTR, CV.YEAR,
CV.MAKE, CV.MODEL, I.D1NAME AS COBORROWER, A.ADDRESS1, A.ADDRESS2,
A.CITY, A.STATE, A.ZIP_STR, L.BALANCE, LP.XPTIMESTAMP, I.TIN ||'-'|| CV.VINSTR
AS TIN_VIN, LP.LOAN_PROPERTY_VALUE
FROM DB2INST1.LOAN L
LEFT OUTER JOIN DB2INST1.ACCOUNTINDIVIDUAL AI ON AI.MEMBER_NBR =
L.MEMBER_NBR AND AI.ACCOUNT_NBR = L.LOAN_NBR
JOIN DB2INST1.INDIVIDUAL I ON I.INDIVIDUAL_ID = AI.INDIVIDUAL_ID
LEFT OUTER JOIN DB2INST1.OWNERSHIPCATEGORY OC ON
OC.OWNERSHIP_CATEGORY_ID = AI.PARTICIPATION_TYPE
JOIN DB2INST1.OWNERSHIPCATEGORYCLASS OCC ON
OCC.OWNERSHIP_CATEGORY_ID = OC.OWNERSHIP_CATEGORY_ID
JOIN DB2INST1.LOANPROPERTY LP ON LP.MEMBER_NBR = L.MEMBER_NBR AND
LP.LOAN_NBR = L.LOAN_NBR
JOIN DB2INST1.LOANCOLLATERAL LC ON LC.MEMBER_NBR = LP.MEMBER_NBR
AND LC.LOAN_NBR = LP.LOAN_NBR
JOIN DB2INST1.COLLATERALVEHICLE CV ON CV.COLLATERAL_ID =
LC.COLLATERAL_ID
JOIN DB2INST1.MEMBERSHIP M ON M.MEMBER_NBR = AI.MEMBER_NBR
JOIN DB2INST1.MEMBERSHIPADDRESS MA ON MA.MEMBER_NBR =
M.MEMBER_NBR
LEFT OUTER JOIN DB2INST1.ADDRESS A ON A.ADDRESS_ID = MA.ADDRESS_ID
WHERE (OCC.OWNERSHIP_CLASS_ID = 1) AND (L.CLOSED = 0 OR L.CLOSED IS
NULL) and (MA.MEMBERSHIP_ADDRESS_TYPE = 1) AND (MA.INDEX = 1) AND
(LP.ITEM_NAME = 'OXVINTEKBOOKDATE') AND (OC.OWNERSHIP_CATEGORY_ID =
3)
GROUP BY L.MEMBER_NBR||'-'|| L.LOAN_NBR, L.MEMBER_NBR, L.LOAN_NBR,
L.OPEN_DATE, OC.OWNERSHIP_CATEGORY_ID, CV.VINSTR, CV.YEAR, CV.MAKE,
CV.MODEL, I.D1NAME, A.ADDRESS1, A.ADDRESS2, A.CITY, A.STATE, A.ZIP_STR,
L.BALANCE, LP.XPTIMESTAMP, I.TIN ||'-'|| CV.VINSTR, LP.LOAN_PROPERTY_VALUE
Query 2: The WHERE clause is only looking at secondary members or co-
borrowers. This query doesn’t have to be this long, but in order to be consistent and
make it easier for future references, I try to duplicate it. All we need is member
number from this query.
21. Having Primary/Secondary names in one row – Cont…
Next Steps…..
- Export Query 2 in excel format.
- Import the Excel into Query 1 and join them by Member number (LEFT or LEFT
OUTER JOIN to include loans even without a co-borrower. An inner join would
only export the ones with co-borrowers).
- Now run the first query with the excel imported
- When exported, the borrowers and co-borrowers will be in one row.
How do you automate such a report?
Say you want to run this report at 1:00am on the 1ST of every month.
- Set up query 2 to run at 12:30am on the 1ST of every month.
- Set up the destination such that it exports into the same folder that query 1 is
grabbing it from.
- Make sure the it always exports with the same name, so the previous file is
always replaced.
- Once this runs at 12:30am, Query 1 will automatically import the updated excel
at 1:00am and export an up to date and accurate report with borrowers and co-
borrowers in one row.
23. Calculations for Analysis – Within the SQL Query
Lets take for example profitability analysis
- Instead of exporting few different extracts and setting up an excel with
formulas, most of the work can be done within the query itself
- Convenient for the end user
(COALESCE (SUM(L.INT_PYR),0) + COALESCE (SUM(L.FEES_PYR),0) +
COALESCE(SUM(T.PERIOD_NSF_FEES_PIN),0) - COALESCE (SUM(S.DIV_PYR),0)) AS
PARTINCOME
COALESCE – If the value is null in the database, it automatically puts in a
ZERO.
Why is this useful?
- If the value is null, the final calculation will be a null too, thus affecting the
report or analysis as a whole.
- Hence, a COALESCE is a very useful function for such calculations
Add this to the SELECT statement after defining the fields. Such functions
are not added to the GROUP BY clause. The GROUP BY clause will have the
individual fields.
RANK BY Clause – Say you want to rank them by income to avoid having the end
user to do this on Excel.
Add the following to the SELECT Statement
RANK () OVER (ORDER BY (COALESCE (SUM(L.INT_PYR),0) + COALESCE
(SUM(L.FEES_PYR),0) + COALESCE(SUM(T.PERIOD_NSF_FEES_PIN),0) - COALESCE
(SUM(S.DIV_PYR),0)) DESC) AS RANKBYINCOME
ORDER BY Clause – Assuming you want to rank it from highest to lowest, use a
DESC [means Descending order]
ORDER BY
COALESCE (SUM(L.INT_PYR),0) + COALESCE (SUM(L.FEES_PYR),0) +
COALESCE(SUM(T.PERIOD_NSF_FEES_PIN),0) - COALESCE (SUM(S.DIV_PYR),0) DESC
24. CAST Statement – Conversion from 1 data type to another
Convert Membership open date to # of years
SELECT
CASE WHEN (CAST((DAYS(CURRENT DATE) - DAYS(M.OPEN_DATE))/365.25 as
INTEGER) BETWEEN 10 AND 19)
WHEN (CAST((DAYS(CURRENT DATE) - DAYS(I.BIRTH_DATE))/365.25 as INTEGER) >=
18) ELSE ‘OTHER’ END AS MEMBERLENGTH
WHERE
(CAST((DAYS(CURRENT DATE) - DAYS(M.OPEN_DATE))/365.25 as INTEGER)
BETWEEN 10 AND 19)
If you want to only display members between 10 and 19, then the CAST
statement can be used in the WHERE Clause
25. Mastered Joins
and automation
of reports!
Now, lets take a
quick look at
how automation
of reports can be
used to
automatically
update charts
and matrices in
excel
26. Cross-Sell Data in SQL
An example of a cross-sell matrix I created on Excel
- The cells say ‘value’ since I didn’t open the source for the data to
populate
- Write a simple SQL using a CASE statement as follows to extract the
following data
The above categories using a CASE statement
CASE WHEN (P.PRODUCT_NAME LIKE '%AUTO%' AND
P.PRODUCT_NAME NOT LIKE '%INDIRECT%') THEN L.BALANCE END AS
DIRECTAUTO, CASE WHEN P.PRODUCT_NAME LIKE '%INDIRECT%' THEN
L.BALANCE END AS INDIRECT,
CASE WHEN P.PRODUCT_NAME LIKE '%MOTORCYCLE%' THEN
L.BALANCE END AS MOTORCYCLE,
CASE WHEN P.PRODUCT_NAME LIKE '%PERSONAL%' THEN L.BALANCE
END AS PERSONAL, CASE WHEN P.PRODUCT_NAME LIKE '%DC%' THEN
L.BALANCE END AS DEBTCONSOLIDATION, CASE WHEN
P.PRODUCT_NAME LIKE '%RECREATIONAL%' THEN L.BALANCE END AS
RV, EP.MEMBER_NBR AS CREDITCARD
Age categories in the SELECT Clause
CASE WHEN (CAST((DAYS(CURRENT DATE) - DAYS(I.BIRTH_DATE))/365.25
as INTEGER) < 18) THEN 'LESS THAN 18'
WHEN (CAST((DAYS(CURRENT DATE) - DAYS(I.BIRTH_DATE))/365.25 as
INTEGER) BETWEEN 18 AND 24) THEN '18 THRU 24'
WHEN (CAST((DAYS(CURRENT DATE) - DAYS(I.BIRTH_DATE))/365.25 as
INTEGER) BETWEEN 25 AND 29) THEN '25 THRU 29'
WHEN (CAST((DAYS(CURRENT DATE) - DAYS(I.BIRTH_DATE))/365.25 as
INTEGER) BETWEEN 30 AND 39) THEN '30 THRU 39'
WHEN (CAST((DAYS(CURRENT DATE) - DAYS(I.BIRTH_DATE))/365.25 as
INTEGER) BETWEEN 40 AND 49) THEN '40 THRU 49'
WHEN (CAST((DAYS(CURRENT DATE) - DAYS(I.BIRTH_DATE))/365.25 as
INTEGER) BETWEEN 50 AND 59) THEN '50 THRU 59'
WHEN (CAST((DAYS(CURRENT DATE) - DAYS(I.BIRTH_DATE))/365.25 as
INTEGER) > 59) THEN 'GREATER THAN 59' END AS AGE_RANGE
27. Cross-Sell Data in SQL …. Cont….
- Now in a different tab, in the same worksheet, list the age categories
used.
- Use the data validation option to point a cell in sheet 1 to it in a LIST
Format
- Point each of the cells in the matrix to the data extracted using SQL –
Use Excel Formulas - Avoid Array formulas – Just simple SUMIFS and
COUNTIFS
- If you are very well versed with excel, you would know that you would
have to go to DATA>>EDIT LINKS>>OPEN SOURCE in order to
populate numbers.
- Various matrices can be designed.
- Above is just an example from one of my projects.
- It tells us the total # of members having a combination of products, the
dollar amount among all those within a combination, and the same
information on new members in that combination.
- A good picture base on Age Range
29. Little Tips
Combine two fields with ‘-’
SELECT L.MEMBER_NBR||'-'|| L.LOAN_NBR AS MEMBER_LOAN
Combine two fields with ‘.’
SELECT L.MEMBER_NBR||‘.'|| L.LOAN_NBR AS MEMBER_LOAN
Incase you have Indirect Loans, look into using the Book Date instead of the
Open Date for Monthly loans, since the ones effective in prior ones wont show
up when Open Date is used.
To do this, join the Loan Table with the Prebookloan Table via the Application #.
The application # in the Prebookloan is the same as the Loan Note Number in the
Loan Table.
FROM DB2INST1.PREBOOKLOAN P
LEFT JOIN DB2INST1.LOAN L ON L.LOAN_NOTE_NBR = P.APLNUM
Use a LEFT JOIN to see all applications and a regular
JOIN to see just the ones booked. Only the booked
applications enter the Loan Table.
Since there is no Booked Status, a CASE Statement
could be used to look at booked loans
CASE WHEN P.STATUS = ‘A’ AND P.BOOKDATE IS NOT NULL THEN
‘BOOKED’
Current Month
WHERE MONTH (T.ENTRY_DATE) = MONTH(CURRENT DATE) AND
YEAR (T.ENTRY_DATE) = YEAR(CURRENT DATE)
Current Year
WHERE YEAR (T.ENTRY_DATE) = YEAR(CURRENT DATE)
31. APPENDIX B
XP2 Fields DATA DICTIONARY
TITLE L.TITLE
PRODUCT NAME P.PRODUCT_NAME
OPEN END CATEGORY L.OPEN_END_CATEGORY
DRAW PERIOD L.HAS_DRAW
CLASSIFICATION L.CLASSIFICATION_CODE
CYCLE L.CYCLE_DAY
PRODUCT CODE P.PRODUCT_CLASS_CODE
OFFICER L.ORIGUSER
ML_ORIGINATOR L.ML_ORIGINATOR_NBR
NOTE NUMBER L.LOAN_NOTE_NBR
STATUS L.CLOSED
LAST CYCLE DATE L.LAST_CYCLE_DATE
BALANCE L.BALANCE
EFFECTIVE PAYMENT L.PMT_BASE
SCHEDULED PAYMENT L.SCHEDULED_PMT
ALTERNATE PAYMENT L.ALT_PMT_AMT
COUPONS L.COUPON
PAYMENT SKIPS L.PAYMENT_SKIP_COUNT
DUE DATE L.NEXT_DUE_DATE
ALTERNATE BEGIN DATE L.ALT_PMT_BEGIN_DATE
GENERATE COUPONS L.NEEDS_COUPONS_PRINTED
PROCESSING GROUP PB.PROCGRP
COUPON DATE L.COUPONS_THRU_DATE
ALTERNATE END DATE L.ALT_PMT_END_DATE
FINAL PAYMENT L.FINAL_PMT_AMT
PREPAYMENT INFORMATION L.PREPAYMENT_INFO_TEXT
FINAL PAYMENT DATE L.FINAL_PMT_DATE
LAST BILL DATE L.LAST_BILL_DATE
PARTIAL PAYMENT L.PARTIAL_PMT
LAST PAYMENT DATE L.LAST_PAYMENT_DATE
TRANSFER DAY L.TRANSFER_DAY
SOURCE ACCOUNT L.PMT_SHR_NBR
SOURCE MEMBER L.PMT_MEMBER_NBR
ORIGINATION DATE L.OPEN_DATE
ORIGINAL AMOUNT L.ORIGINAL_AMT
PAYMENT METHOD L.PMT_SOURCE
32. APPENDIX B
XP2 Fields DATA DICTIONARY
FIRST PAYMENT DATE L.FIRST_PMT_DATE
PAYMENT FREQUENCY L.FREQ
LIMIT L.LIMIT
DUE DATE L.NEXT_DUE_DATE
DAYS PAST DUE AG.DAYSDEL
MONTHS PAST DUE AG.DELMTH
PAYMENTS PAST DUE AG.DELAMT
INTEREST ACCRUED DATE L.INT_ACCRUED
PAYMENT INTEREST DUE L.INT_DUE
APR L.APR
MONTHLY TERM L.MONTHLY_TERM
ORIGINAL RATE L.ORIG_RATE
INTEREST RATE L.INS_RATE
ALTERNATE RATE L.INS_RATE_ALT
INTEREST TYPE INDICATOR L.INTEREST_TYPE
LAST RATE CHANGE L.VR_CHANGE_DATE
BALANCE LIMIT L.LIMIT
AMORTIZATION L.AMTZ_METHOD
BASE RATE L.BASE_RATE
WAIVE DELINQUENCY NOTICE L.DELQ_NOTICE_WAIVE
PREPAYMENT PENALTY DATE L.REPMT_PENALTY_DATE
OPEN-END LOAN L.IS_OPEN_END
WAIVE BILLING NOTICE L.WAIVE_BILLING_NOTICE
STATEMENT TYPE L.STMT_TYPE
PREPAYMENT PENALTY L.REPMT_PENALTY_AMT
VARIABLE RATE PMT CHANGE L.VAR_PMT_CHNG_CODE
STATEMENT CYCLE L.STMT_CYCL
LAST STATEMENT DATE L.STMT_LAST_THRU_DATE
FORM 1098 OPTION L.RESIDENCE_1098_CODE
STATEMENT FREQUENCY L.STMT_FREQ
VARIABLE RATE CODE L.VAR_RATE_CODE
33. APPENDIX C
XP2 FIELDS DATA DICTIONARY
AVAILABLE S.LAST_AVAIL_BAL
BALANCE S.BALANCE
BONUS DIFFERENTIAL S.DIV_RATE_DIFFERENTIAL
CUSTODIAL/TRUST S.IS_INVESTOR_CUSTODIAL_TI_ACCT
LAST CONTACT S.LAST_CONT_DATE
LAST DIVIDEND PAID S.DIV_LAST_PAID
OPENING DEPOSIT P.OPEN_AMT
PLAN BENEFICIARIES S.HAS_BENEFECIARIES
PRODUCT CODE P.PRODUCT_CODE
PRODUCT NAME P.PRODUCT_NAME
SPECIAL FUNDS AMOUNT S.SPECIAL_HOLD_AMT
STATUS S.CLOSED
TO COLLECTION S.INCOL
WRITTEN OFF S.WOFF