SELF JOIN

In my experience, the SELF JOIN is almost as rare as the CROSS JOIN. This is due to the limited opportunities existing in most data to actually make use of it. It is particularly useful when attempting to capture hierarchal relationships or simply when there is a need to capture data, existing across multiple rows, within a single row. While this join type is often referred to as a SELF JOIN, in practice, it’s a LEFT JOIN with the same table on both sides of the LEFT JOIN keywords. Each instance requires a different name, so table aliases are a must. This eliminates the table and column ambiguity that would otherwise occur in the ON and SELECT clauses.

One common example can be found within the data responsible for capturing information on a company’s products and the corresponding product categories. Each product belongs within a category and that category may roll-up to another, broader category. The purpose of this broader or parent category is to group related categories together. Another common example can be found in human resource data where there exists a relationship between managers and employees. Typically, a manager has one or more employees, and an employee directly reports to one manager.

Let’s explore both examples, individually, and then walk through an example that is not so common. The data used in the first two examples on this page can be found at livesql.oracle.com.

Product Category Relationships
In this example, we’ll use the categories table below. Within this table, there is one row per product category. Within each row, the parent category ID value associated with the specific category’s parent category, if one exists, is recorded. By having the parent category ID within each row, we can gather each category’s parent information by traversing the same table and finding where the parent category ID exists as a category ID. For example, the category, “hardware1” has a parent category ID value of 10. In the row above, this parent category ID value can be found within the category ID column. Therefore, “hardware” is the parent category of “hardware1” and has a category description of “computer hardware and peripherals.”

category_namecategory_descriptioncategory_idparent_category_id
hardwarecomputer hardware and peripherals1090
hardware1monitors1110
hardware2printers1210
hardware3harddisks1310
hardware4memory components/upgrades1410
hardware5processors, sound and video cards, network cards, motherboards1510
hardware6keyboards, mouses, mouse pads1610
hardware7other peripherals (CD-ROM, DVD, tape cartridge drives, …)1710
hardware8miscellaneous hardware (cables, screws, power supplies …)1910
softwarecomputer software2090
software1spreadsheet software2120
software2word processing software2220
software3database software2320
software4operating systems2420
software5software development tools (including languages)2520
software6miscellaneous software2920
office equipmentoffice furniture and supplies3090
office1capitalizable assets (desks, chairs, phones …)3130
office2office supplies for daily use (pencils, erasers, staples, …)3230
office3manuals, other books3330
office4miscellaneous office supplies3930
online catalogcatalog of computer hardware, software, and office equipment90

This same process can be carried out manually for each category; however, the goal is to approach this programmatically by using two aliased instances of the categories table in a LEFT JOIN operation. The ON clause will contain the same instructions we processed manually when traversing the rows for matches. When a match is found, the category’s parent information, if it exists, will be represented within the same row, side by side.

Below is the code used to achieve this task and the corresponding result set. I’ve ordered the result set by the child category ID for readability.

-- Retrieve each category and category's parent category information within the same row.
SELECT
    child_category.category_id,
    child_category.category_name,
    child_category.category_description,
    parent_category.category_id AS parent_category_id,
    parent_category.category_name AS parent_category_name,
    parent_category.category_description AS parent_category_description
FROM
    oe.categories_tab child_category
    LEFT JOIN
    oe.categories_tab parent_category
        ON child_category.parent_category_id = parent_category.category_id
ORDER BY
    child_category.category_id;
category_idcategory_namecategory_descriptionparent_category_idparent_category_nameparent_category_description
10hardwarecomputer hardware and peripherals90online catalogcatalog of computer hardware, software, and office equipment
11hardware1monitors10hardwarecomputer hardware and peripherals
12hardware2printers10hardwarecomputer hardware and peripherals
13hardware3harddisks10hardwarecomputer hardware and peripherals
14hardware4memory components/upgrades10hardwarecomputer hardware and peripherals
15hardware5processors, sound and video cards, network cards, motherboards10hardwarecomputer hardware and peripherals
16hardware6keyboards, mouses, mouse pads10hardwarecomputer hardware and peripherals
17hardware7other peripherals (CD-ROM, DVD, tape cartridge drives, …)10hardwarecomputer hardware and peripherals
19hardware8miscellaneous hardware (cables, screws, power supplies …)10hardwarecomputer hardware and peripherals
20softwarecomputer software90online catalogcatalog of computer hardware, software, and office equipment
21software1spreadsheet software20softwarecomputer software
22software2word processing software20softwarecomputer software
23software3database software20softwarecomputer software
24software4operating systems20softwarecomputer software
25software5software development tools (including languages)20softwarecomputer software
29software6miscellaneous software20softwarecomputer software
30office equipmentoffice furniture and supplies90online catalogcatalog of computer hardware, software, and office equipment
31office1capitalizable assets (desks, chairs, phones …)30office equipmentoffice furniture and supplies
32office2office supplies for daily use (pencils, erasers, staples, …)30office equipmentoffice furniture and supplies
33office3manuals, other books30office equipmentoffice furniture and supplies
39office4miscellaneous office supplies30office equipmentoffice furniture and supplies
90online catalogcatalog of computer hardware, software, and office equipment

Notice how the row corresponding to category ID 90 (i.e., online catalog) doesn’t contain parent category information. This is because it doesn’t have one.

Employee-Manager Relationships
In this example, we’ll use the employees table below. Within this table, there is one row per employee. Within each row, the manager ID value associated with the specific employee’s manager is recorded. The absence of a manager ID value is indicative of an employee not reporting directly to another employee, or more simply put, an unmanaged employee. Because each employee’s manager ID value is captured within the same row, we can gather the employee’s manager information by traversing the same table and finding the row where the manager ID value exists as an employee ID value. For example, Neena Kochhar (i.e., employee ID 101) reports to the employee with an employee ID value of 100. Based on the table, this employee ID value corresponds to Steven King.

employee_idfirst_namelast_nameemailphone_numberhire_datejob_idsalarycommission_pctmanager_iddepartment_id
100StevenKingSKING515.123.456717-Jun-03AD_PRES2400090
101NeenaKochharNKOCHHAR515.123.456821-Sep-05AD_VP1700010090
102LexDe HaanLDEHAAN515.123.456913-Jan-01AD_VP1700010090
103AlexanderHunoldAHUNOLD590.423.45673-Jan-06IT_PROG900010260
104BruceErnstBERNST590.423.456821-May-07IT_PROG600010360
105DavidAustinDAUSTIN590.423.456925-Jun-05IT_PROG480010360
106ValliPataballaVPATABAL590.423.45605-Feb-06IT_PROG480010360
107DianaLorentzDLORENTZ590.423.55677-Feb-07IT_PROG420010360
108NancyGreenbergNGREENBE515.124.456917-Aug-02FI_MGR12008101100
109DanielFavietDFAVIET515.124.416916-Aug-02FI_ACCOUNT9000108100
110JohnChenJCHEN515.124.426928-Sep-05FI_ACCOUNT8200108100
111IsmaelSciarraISCIARRA515.124.436930-Sep-05FI_ACCOUNT7700108100
112Jose ManuelUrmanJMURMAN515.124.44697-Mar-06FI_ACCOUNT7800108100
113LuisPoppLPOPP515.124.45677-Dec-07FI_ACCOUNT6900108100
114DenRaphaelyDRAPHEAL515.127.45617-Dec-02PU_MAN1100010030
115AlexanderKhooAKHOO515.127.456218-May-03PU_CLERK310011430
116ShelliBaidaSBAIDA515.127.456324-Dec-05PU_CLERK290011430
117SigalTobiasSTOBIAS515.127.456424-Jul-05PU_CLERK280011430
118GuyHimuroGHIMURO515.127.456515-Nov-06PU_CLERK260011430
119KarenColmenaresKCOLMENA515.127.456610-Aug-07PU_CLERK250011430
120MatthewWeissMWEISS650.123.123418-Jul-04ST_MAN800010050
121AdamFrippAFRIPP650.123.223410-Apr-05ST_MAN820010050
122PayamKauflingPKAUFLIN650.123.32341-May-03ST_MAN790010050
123ShantaVollmanSVOLLMAN650.123.423410-Oct-05ST_MAN650010050
124KevinMourgosKMOURGOS650.123.523416-Nov-07ST_MAN580010050
125JuliaNayerJNAYER650.124.121416-Jul-05ST_CLERK320012050
126IreneMikkilineniIMIKKILI650.124.122428-Sep-06ST_CLERK270012050
127JamesLandryJLANDRY650.124.133414-Jan-07ST_CLERK240012050
128StevenMarkleSMARKLE650.124.14348-Mar-08ST_CLERK220012050
129LauraBissotLBISSOT650.124.523420-Aug-05ST_CLERK330012150
130MozheAtkinsonMATKINSO650.124.623430-Oct-05ST_CLERK280012150
131JamesMarlowJAMRLOW650.124.723416-Feb-05ST_CLERK250012150
132TJOlsonTJOLSON650.124.823410-Apr-07ST_CLERK210012150
133JasonMallinJMALLIN650.127.193414-Jun-04ST_CLERK330012250
134MichaelRogersMROGERS650.127.183426-Aug-06ST_CLERK290012250
135KiGeeKGEE650.127.173412-Dec-07ST_CLERK240012250
136HazelPhiltankerHPHILTAN650.127.16346-Feb-08ST_CLERK220012250
137RenskeLadwigRLADWIG650.121.123414-Jul-03ST_CLERK360012350
138StephenStilesSSTILES650.121.203426-Oct-05ST_CLERK320012350
139JohnSeoJSEO650.121.201912-Feb-06ST_CLERK270012350
140JoshuaPatelJPATEL650.121.18346-Apr-06ST_CLERK250012350
141TrennaRajsTRAJS650.121.800917-Oct-03ST_CLERK350012450
142CurtisDaviesCDAVIES650.121.299429-Jan-05ST_CLERK310012450
143RandallMatosRMATOS650.121.287415-Mar-06ST_CLERK260012450
144PeterVargasPVARGAS650.121.20049-Jul-06ST_CLERK250012450
145JohnRussellJRUSSEL011.44.1344.4292681-Oct-04SA_MAN140000.410080
146KarenPartnersKPARTNER011.44.1344.4672685-Jan-05SA_MAN135000.310080
147AlbertoErrazurizAERRAZUR011.44.1344.42927810-Mar-05SA_MAN120000.310080
148GeraldCambraultGCAMBRAU011.44.1344.61926815-Oct-07SA_MAN110000.310080
149EleniZlotkeyEZLOTKEY011.44.1344.42901829-Jan-08SA_MAN105000.210080
150PeterTuckerPTUCKER011.44.1344.12926830-Jan-05SA_REP100000.314580
151DavidBernsteinDBERNSTE011.44.1344.34526824-Mar-05SA_REP95000.2514580
152PeterHallPHALL011.44.1344.47896820-Aug-05SA_REP90000.2514580
153ChristopherOlsenCOLSEN011.44.1344.49871830-Mar-06SA_REP80000.214580
154NanetteCambraultNCAMBRAU011.44.1344.9876689-Dec-06SA_REP75000.214580
155OliverTuvaultOTUVAULT011.44.1344.48650823-Nov-07SA_REP70000.1514580
156JanetteKingJKING011.44.1345.42926830-Jan-04SA_REP100000.3514680
157PatrickSullyPSULLY011.44.1345.9292684-Mar-04SA_REP95000.3514680
158AllanMcEwenAMCEWEN011.44.1345.8292681-Aug-04SA_REP90000.3514680
159LindseySmithLSMITH011.44.1345.72926810-Mar-05SA_REP80000.314680
160LouiseDoranLDORAN011.44.1345.62926815-Dec-05SA_REP75000.314680
161SarathSewallSSEWALL011.44.1345.5292683-Nov-06SA_REP70000.2514680
162ClaraVishneyCVISHNEY011.44.1346.12926811-Nov-05SA_REP105000.2514780
163DanielleGreeneDGREENE011.44.1346.22926819-Mar-07SA_REP95000.1514780
164MatteaMarvinsMMARVINS011.44.1346.32926824-Jan-08SA_REP72000.114780
165DavidLeeDLEE011.44.1346.52926823-Feb-08SA_REP68000.114780
166SundarAndeSANDE011.44.1346.62926824-Mar-08SA_REP64000.114780
167AmitBandaABANDA011.44.1346.72926821-Apr-08SA_REP62000.114780
168LisaOzerLOZER011.44.1343.92926811-Mar-05SA_REP115000.2514880
169HarrisonBloomHBLOOM011.44.1343.82926823-Mar-06SA_REP100000.214880
170TaylerFoxTFOX011.44.1343.72926824-Jan-06SA_REP96000.214880
171WilliamSmithWSMITH011.44.1343.62926823-Feb-07SA_REP74000.1514880
172ElizabethBatesEBATES011.44.1343.52926824-Mar-07SA_REP73000.1514880
173SunditaKumarSKUMAR011.44.1343.32926821-Apr-08SA_REP61000.114880
174EllenAbelEABEL011.44.1644.42926711-May-04SA_REP110000.314980
175AlyssaHuttonAHUTTON011.44.1644.42926619-Mar-05SA_REP88000.2514980
176JonathonTaylorJTAYLOR011.44.1644.42926524-Mar-06SA_REP86000.214980
177JackLivingstonJLIVINGS011.44.1644.42926423-Apr-06SA_REP84000.214980
178KimberelyGrantKGRANT011.44.1644.42926324-May-07SA_REP70000.15149
179CharlesJohnsonCJOHNSON011.44.1644.4292624-Jan-08SA_REP62000.114980
180WinstonTaylorWTAYLOR650.507.987624-Jan-06SH_CLERK320012050
181JeanFleaurJFLEAUR650.507.987723-Feb-06SH_CLERK310012050
182MarthaSullivanMSULLIVA650.507.987821-Jun-07SH_CLERK250012050
183GirardGeoniGGEONI650.507.98793-Feb-08SH_CLERK280012050
184NanditaSarchandNSARCHAN650.509.187627-Jan-04SH_CLERK420012150
185AlexisBullABULL650.509.287620-Feb-05SH_CLERK410012150
186JuliaDellingerJDELLING650.509.387624-Jun-06SH_CLERK340012150
187AnthonyCabrioACABRIO650.509.48767-Feb-07SH_CLERK300012150
188KellyChungKCHUNG650.505.187614-Jun-05SH_CLERK380012250
189JenniferDillyJDILLY650.505.287613-Aug-05SH_CLERK360012250
190TimothyGatesTGATES650.505.387611-Jul-06SH_CLERK290012250
191RandallPerkinsRPERKINS650.505.487619-Dec-07SH_CLERK250012250
192SarahBellSBELL650.501.18764-Feb-04SH_CLERK400012350
193BritneyEverettBEVERETT650.501.28763-Mar-05SH_CLERK390012350
194SamuelMcCainSMCCAIN650.501.38761-Jul-06SH_CLERK320012350
195VanceJonesVJONES650.501.487617-Mar-07SH_CLERK280012350
196AlanaWalshAWALSH650.507.981124-Apr-06SH_CLERK310012450
197KevinFeeneyKFEENEY650.507.982223-May-06SH_CLERK300012450
198DonaldOConnellDOCONNEL650.507.983321-Jun-07SH_CLERK260012450
199DouglasGrantDGRANT650.507.984413-Jan-08SH_CLERK260012450
200JenniferWhalenJWHALEN515.123.444417-Sep-03AD_ASST440010110
201MichaelHartsteinMHARTSTE515.123.555517-Feb-04MK_MAN1300010020
202PatFayPFAY603.123.666617-Aug-05MK_REP600020120
203SusanMavrisSMAVRIS515.123.77777-Jun-02HR_REP650010140
204HermannBaerHBAER515.123.88887-Jun-02PR_REP1000010170
205ShelleyHigginsSHIGGINS515.123.80807-Jun-02AC_MGR12008101110
206WilliamGietzWGIETZ515.123.81817-Jun-02AC_ACCOUNT8300205110

Like the first example on product category relationships, this manual process can be approached programmatically. See the code used to do so and the corresponding result set, below. For simplicity, only a subset of the preexisting columns or attributes are included for each employee and corresponding manager.

-- Retrieve each employee's and corresponding manager's information.
SELECT
	hr.employees.employee_id,
	hr.employees.first_name,
	hr.employees.last_name,
	hr.employees.salary AS salary,
	manager.employee_id AS manager_id,
	manager.first_name AS manager_first_name,
	manager.last_name AS manager_last_name,
	manager.salary AS manager_salary
FROM
	hr.employees
	LEFT JOIN
	hr.employees manager
		ON  hr.employees.manager_id = manager.employee_id;
employee_idfirst_namelast_namesalarymanager_idmanager_first_namemanager_last_namemanager_salary
101NeenaKochhar17000100StevenKing24000
102LexDe Haan17000100StevenKing24000
114DenRaphaely11000100StevenKing24000
120MatthewWeiss8000100StevenKing24000
121AdamFripp8200100StevenKing24000
122PayamKaufling7900100StevenKing24000
123ShantaVollman6500100StevenKing24000
124KevinMourgos5800100StevenKing24000
145JohnRussell14000100StevenKing24000
146KarenPartners13500100StevenKing24000
147AlbertoErrazuriz12000100StevenKing24000
148GeraldCambrault11000100StevenKing24000
149EleniZlotkey10500100StevenKing24000
201MichaelHartstein13000100StevenKing24000
108NancyGreenberg12008101NeenaKochhar17000
200JenniferWhalen4400101NeenaKochhar17000
203SusanMavris6500101NeenaKochhar17000
204HermannBaer10000101NeenaKochhar17000
205ShelleyHiggins12008101NeenaKochhar17000
103AlexanderHunold9000102LexDe Haan17000
104BruceErnst6000103AlexanderHunold9000
105DavidAustin4800103AlexanderHunold9000
106ValliPataballa4800103AlexanderHunold9000
107DianaLorentz4200103AlexanderHunold9000
109DanielFaviet9000108NancyGreenberg12008
110JohnChen8200108NancyGreenberg12008
111IsmaelSciarra7700108NancyGreenberg12008
112Jose ManuelUrman7800108NancyGreenberg12008
113LuisPopp6900108NancyGreenberg12008
115AlexanderKhoo3100114DenRaphaely11000
116ShelliBaida2900114DenRaphaely11000
117SigalTobias2800114DenRaphaely11000
118GuyHimuro2600114DenRaphaely11000
119KarenColmenares2500114DenRaphaely11000
125JuliaNayer3200120MatthewWeiss8000
126IreneMikkilineni2700120MatthewWeiss8000
127JamesLandry2400120MatthewWeiss8000
128StevenMarkle2200120MatthewWeiss8000
180WinstonTaylor3200120MatthewWeiss8000
181JeanFleaur3100120MatthewWeiss8000
182MarthaSullivan2500120MatthewWeiss8000
183GirardGeoni2800120MatthewWeiss8000
129LauraBissot3300121AdamFripp8200
130MozheAtkinson2800121AdamFripp8200
131JamesMarlow2500121AdamFripp8200
132TJOlson2100121AdamFripp8200
184NanditaSarchand4200121AdamFripp8200
185AlexisBull4100121AdamFripp8200
186JuliaDellinger3400121AdamFripp8200
187AnthonyCabrio3000121AdamFripp8200
133JasonMallin3300122PayamKaufling7900
134MichaelRogers2900122PayamKaufling7900
135KiGee2400122PayamKaufling7900
136HazelPhiltanker2200122PayamKaufling7900
188KellyChung3800122PayamKaufling7900
189JenniferDilly3600122PayamKaufling7900
190TimothyGates2900122PayamKaufling7900
191RandallPerkins2500122PayamKaufling7900
137RenskeLadwig3600123ShantaVollman6500
138StephenStiles3200123ShantaVollman6500
139JohnSeo2700123ShantaVollman6500
140JoshuaPatel2500123ShantaVollman6500
192SarahBell4000123ShantaVollman6500
193BritneyEverett3900123ShantaVollman6500
194SamuelMcCain3200123ShantaVollman6500
195VanceJones2800123ShantaVollman6500
141TrennaRajs3500124KevinMourgos5800
142CurtisDavies3100124KevinMourgos5800
143RandallMatos2600124KevinMourgos5800
144PeterVargas2500124KevinMourgos5800
196AlanaWalsh3100124KevinMourgos5800
197KevinFeeney3000124KevinMourgos5800
198DonaldOConnell2600124KevinMourgos5800
199DouglasGrant2600124KevinMourgos5800
150PeterTucker10000145JohnRussell14000
151DavidBernstein9500145JohnRussell14000
152PeterHall9000145JohnRussell14000
153ChristopherOlsen8000145JohnRussell14000
154NanetteCambrault7500145JohnRussell14000
155OliverTuvault7000145JohnRussell14000
156JanetteKing10000146KarenPartners13500
157PatrickSully9500146KarenPartners13500
158AllanMcEwen9000146KarenPartners13500
159LindseySmith8000146KarenPartners13500
160LouiseDoran7500146KarenPartners13500
161SarathSewall7000146KarenPartners13500
162ClaraVishney10500147AlbertoErrazuriz12000
163DanielleGreene9500147AlbertoErrazuriz12000
164MatteaMarvins7200147AlbertoErrazuriz12000
165DavidLee6800147AlbertoErrazuriz12000
166SundarAnde6400147AlbertoErrazuriz12000
167AmitBanda6200147AlbertoErrazuriz12000
168LisaOzer11500148GeraldCambrault11000
169HarrisonBloom10000148GeraldCambrault11000
170TaylerFox9600148GeraldCambrault11000
171WilliamSmith7400148GeraldCambrault11000
172ElizabethBates7300148GeraldCambrault11000
173SunditaKumar6100148GeraldCambrault11000
174EllenAbel11000149EleniZlotkey10500
175AlyssaHutton8800149EleniZlotkey10500
176JonathonTaylor8600149EleniZlotkey10500
177JackLivingston8400149EleniZlotkey10500
178KimberelyGrant7000149EleniZlotkey10500
179CharlesJohnson6200149EleniZlotkey10500
202PatFay6000201MichaelHartstein13000
206WilliamGietz8300205ShelleyHiggins12008
100StevenKing24000

Step-rate Mortgages
A step-rate mortgage is one where the interest rate increases in a series of steps over time and for a specific duration. These steps and corresponding details are often conveyed in a schedule or step-rate addendum. In the table below, there exists a handful of mortgage loan account numbers and the associated step rate addendum data. There is one row per account number and step number. All data is fictional.

acct_numstep_numint_ratepi_amt
6358218216121000
635821821622.1251125
635821821632.32500000000000021325
635821821642.751425
4585365392132000
458536539223.1252125
458536539233.252325
458536539243.752425
458536539253.77499999999999992500
480713788814.251300
480713788824.32500000000000021345
480713788834.34999999999999961375
480713788844.451400
801680620612.251200
801680620622.6251350
801680620632.751425

Now, imagine you’re given the following task: for each account and step number, compare the current step’s data with the next step’s data by displaying both steps’ data in a single row. In addition, provide the amount the principal and interest increased from step to step based on the comparison of principal and interest amounts for the steps. That is, compute the difference between the next step’s principal and interest amount and the current step’s principal and interest amount. Again, your solution should contain the step’s data and the subsequent step’s data, if one exists, in a single row for quick comparison.

Unlike the first two examples where a relationship between two rows was explicitly captured in a single row (e.g., an employee ID and corresponding manager ID), here the relationship between two or more rows is implied by the step numbers. Each account’s step numbers are sequential, one followed by two, two followed by three, and so forth. This fact can be relied upon when developing a solution to the task. Specifically, it can be added to the ON clause to ensure the necessary step comparisons are made by stitching together the appropriate rows (e.g., 1 compared to 2, 2 compared to 3, etc.). The first condition necessary in the ON clause is straightforward. The comparisons need to be made using step data from the same account number. The second and not so common condition is the step number in the current row is equal to the next step number less one. When attempting to make sense of the second condition, it’s important to remember two instances of the same table are being used.

One possible solution and corresponding result set can be found below. Keep in mind, with the advent of window or analytic functions, this problem can be solved in an arguably more intuitive manner. Row reference functions are not the focus of this page; however, an alternative solution utilizing them can be found below the initial solution.

-- Using LEFT JOIN to solve.
SELECT
    current_step.acct_num,
    current_step.step_num AS current_step_num,
    current_step.int_rate AS current_int_rate,
    current_step.pi_amt AS current_pi_amt,
    next_step.step_num AS next_step_num,
    next_step.int_rate AS next_int_rate,
    next_step.pi_amt AS next_pi_amt,
    next_step.pi_amt - current_step.pi_amt AS amt_increase
FROM
    pi_loan current_step
    LEFT JOIN
    pi_loan next_step
        ON current_step.acct_num = next_step.acct_num
        AND current_step.step_num = (next_step.step_num - 1)
ORDER BY
    current_step.acct_num, current_step.step_num;

-- Using Window/analytic function to solve.
SELECT
    pi_loan.acct_num,
    pi_loan.step_num AS current_step_num,
    pi_loan.int_rate AS current_int_rate,
    pi_loan.pi_amt AS current_pi_amt,
    LEAD(pi_loan.step_num, 1, NULL) OVER(
    	PARTITION BY pi_loan.acct_num
    	ORDER BY pi_loan.step_num
    ) AS next_step_num,
    LEAD(pi_loan.int_rate, 1, NULL) OVER(
        PARTITION BY pi_loan.acct_num
        ORDER BY pi_loan.step_num
    ) AS next_int_rate,
    LEAD(pi_loan.pi_amt, 1, NULL) OVER(
        PARTITION BY pi_loan.acct_num
        ORDER BY pi_loan.step_num
    ) AS next_pi_amt,
    (
    LEAD(pi_loan.pi_amt, 1, NULL) OVER(
        PARTITION BY pi_loan.acct_num
        ORDER BY pi_loan.step_num
    )
    - pi_loan.pi_amt
    ) AS amt_increase
FROM
    pi_loan
ORDER BY
    pi_loan.acct_num,
    pi_loan.step_num;
acct_numcurrent_step_numcurrent_int_ratecurrent_pi_amtnext_step_numnext_int_ratenext_pi_amtamt_increase
458536539213200023.1252125125
458536539223.125212533.252325200
458536539233.25232543.752425100
458536539243.75242553.775250075
458536539253.7752500
480713788814.25130024.325134545
480713788824.325134534.35137530
480713788834.35137544.45140025
480713788844.451400
635821821612100022.1251125125
635821821622.125112532.3251325200
635821821632.325132542.751425100
635821821642.751425
801680620612.25120022.6251350150
801680620622.625135032.75142575
801680620632.751425

The SELF JOIN has a special place in my heart due to the initial difficulty I felt when attempting to understand it. In the beginning, the ON clause simply didn’t click for me. Hopefully, as a result of reading this, you are able to avoid the headache I endured or at least minimize the headache’s duration.

Knowledge Check
If you’d like to confirm your understanding on JOINS and other fundamental concepts, consider solving a handful of my practice problems here.