<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maurine Nyongesa</title>
    <description>The latest articles on DEV Community by Maurine Nyongesa (@maurine).</description>
    <link>https://dev.to/maurine</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2195188%2Fc131720c-5708-44eb-b156-0cd4ad12a07c.jpg</url>
      <title>DEV Community: Maurine Nyongesa</title>
      <link>https://dev.to/maurine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maurine"/>
    <language>en</language>
    <item>
      <title>Financial Risk Analysis in Excel: How I Used COUNTIFS, AVERAGEIF &amp; Pivot Tables to Uncover Loan Default Patterns</title>
      <dc:creator>Maurine Nyongesa</dc:creator>
      <pubDate>Wed, 18 Mar 2026 06:25:44 +0000</pubDate>
      <link>https://dev.to/maurine/financial-risk-analysis-in-excel-how-i-used-countifs-averageif-pivot-tables-to-uncover-loan-1nfn</link>
      <guid>https://dev.to/maurine/financial-risk-analysis-in-excel-how-i-used-countifs-averageif-pivot-tables-to-uncover-loan-1nfn</guid>
      <description>&lt;h2&gt;
  
  
  Tool: Microsoft Excel | Dataset: 1,000 loans | Period: 2018–2023
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This project is a comprehensive loan portfolio analysis built entirely in Excel. The goal was to understand how &lt;strong&gt;borrower characteristics influence loan issuance, default behavior&lt;/strong&gt;, and &lt;strong&gt;overall portfolio risk&lt;/strong&gt; — and to answer five specific credit risk questions that financial institutions deal with daily:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What Is the Overall Health of the Loan Portfolio?&lt;/strong&gt;
— 37.5% of 1,000 loans ended in default or charge-off. That number alone demands investigation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does Loan Grade Reliably Predict Default Risk?&lt;/strong&gt;
Grade A and B loans recorded 0% bad loan rates. Grade D hit 79%. Grade E reached 100%.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which Borrower Characteristics Drive the Highest Risk?&lt;/strong&gt; 
Credit score below 650 produced a 77–100% bad loan rate. DTI above 30% pushed default rates to nearly 45%.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does Repayment Period Influence Default Probability?&lt;/strong&gt;
48-month loans carried the highest bad rate at 39.6%, marginally ahead of 36-month (38.8%) and 60-month (34.1%) loans.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Has Underwriting Quality Changed Over Time?&lt;/strong&gt;
Bad loan rates fluctuated between 33.3% (2021) and 41.5% (2023), with 2023 marking the worst recent vintage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Through &lt;strong&gt;segmentation analysis, pivot modeling, and time-trend evaluation&lt;/strong&gt;, this analysis simulates how a financial institution would &lt;strong&gt;assess portfolio health, risk concentration, and lending strategy — combining issuance behavior, risk drivers, and repayment performance into a single unified framework.&lt;/strong&gt;&lt;br&gt;
The objective was not just to visualize data. It was to let the data answer something.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Dataset
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1,000 loan records across 13 columns&lt;/strong&gt;, covering two things: who the borrower is, and what happened to the loan.  &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;What It Tells Us&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Loan_ID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique loan identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Issue_Date&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When the loan was issued (2018–2023)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Repayment_Period (Months)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Loan term — 36, 48, or 60 months&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Loan_Amount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Principal borrowed (USD)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Interest_Rate (%)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Annual interest rate on the loan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Annual_Income&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Borrower's declared yearly income (USD)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Debt_to_Income_Ratio (%)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Monthly debt obligations as % of gross income&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Employment_Length (Years)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Years employed at time of application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Home_Ownership&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rent / Own / Mortgage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Loan_Purpose&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Medical, Car, Business, Education, Home Improvement, Debt Consolidation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Credit_Score&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Borrower credit score at issuance (550–800)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Loan_Grade&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lender-assigned risk grade — A (lowest risk) to E (highest)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Loan_Status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;The target variable&lt;/strong&gt; — Fully Paid / Default / Charged Off&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  What This Analysis Covers
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Portfolio Overview&lt;/strong&gt; — baseline KPIs: total loans, volume, fully paid rate, bad loan rate, average credit score, interest rate, and income.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk Segmentation&lt;/strong&gt; — bad loan rates broken down by loan grade, credit score band, DTI bracket, loan purpose, and home ownership.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repayment &amp;amp; Issuance Trends&lt;/strong&gt; — year-over-year portfolio performance from 2018–2023 and default rates across 36, 48, and 60-month terms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grade × Status Cross-Tabulation&lt;/strong&gt; — how each loan grade distributes across Fully Paid, Default, and Charged Off outcomes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommendations&lt;/strong&gt; — data-backed actions for underwriting, risk concentration, and portfolio strategy
All analysis was done in &lt;strong&gt;Microsoft Excel only&lt;/strong&gt; — no Python, no SQL, no Power BI. Just formulas, pivot tables, conditional formatting, and charts.
&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Setting Up the Analysis — Helper Columns First&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Before writing a single summary formula, two helper columns were added directly to the raw data sheet. These columns powered every calculation that followed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Helper Column 1 — Bad Loan Flag
&lt;/h3&gt;

&lt;p&gt;A new column called &lt;strong&gt;Bad_Loan&lt;/strong&gt; was created using:&lt;br&gt;&lt;br&gt;
&lt;code&gt;=IF(OR(M2="Default",M2="Charged Off"),1,0)&lt;/code&gt;&lt;br&gt;&lt;br&gt;
This assigned a &lt;strong&gt;1&lt;/strong&gt; to every loan that &lt;strong&gt;defaulted or was charged off&lt;/strong&gt;, and a &lt;strong&gt;0&lt;/strong&gt; to every &lt;strong&gt;fully paid loan&lt;/strong&gt;. Because the column contains only 1s and 0s, taking the average of this column at any level of segmentation instantly returns the bad loan rate as a decimal.  &lt;/p&gt;
&lt;h3&gt;
  
  
  Helper Column 2 — Issue Year
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Year&lt;/strong&gt; column was extracted from the Issue Date column for all trend analysis:&lt;br&gt;&lt;br&gt;
&lt;code&gt;=YEAR(B2)&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Every segmentation formula then followed one of these patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Overall bad loan rate
=AVERAGE(N2:N1001)

-- Segmented bad loan rate (one condition)
=AVERAGEIF(criteria_range, criteria, N2:N1001)

-- Segmented bad loan rate (multiple conditions)
=AVERAGEIFS(N2:N1001, criteria_range_1, criteria_1, criteria_range_2, criteria_2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note on AVERAGEIF vs AVERAGEIFS:&lt;/strong&gt; The argument order is different and easy to mix up.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;AVERAGEIF&lt;/strong&gt; → range, criteria, average_range (average range last)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;AVERAGEIFS&lt;/strong&gt; → average_range, criteria_range, criteria (average range first)  &lt;/p&gt;
&lt;h4&gt;
  
  
  Finding 1 — The Portfolio is Significantly Non-Performing
&lt;/h4&gt;

&lt;p&gt;The first question was straightforward: what does the overall portfolio health look like?  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Formulas used:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Count per status
=COUNTIF($M$2:$M$1001,"Fully Paid")
=COUNTIF($M$2:$M$1001,"Default")
=COUNTIF($M$2:$M$1001,"Charged Off")

-- Percentage of portfolio
=COUNTIF($M$2:$M$1001,"Fully Paid")/COUNTA($A$2:$A$1001)

-- Bad loan rate (using helper column)
=AVERAGE($N$2:$N$1001)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjx05xi46uhoa7f8luhg4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjx05xi46uhoa7f8luhg4.png" alt=" " width="410" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt; More than one in three loans in this portfolio failed to perform. A 37.5% bad loan rate would trigger immediate portfolio review in any real lending institution. But an overall rate alone doesn't tell you where the problem is — that requires segmentation. &lt;/p&gt;

&lt;h4&gt;
  
  
  Finding 2 — Loan Grade is a Near-Perfect Risk Predictor
&lt;/h4&gt;

&lt;p&gt;Loan grade is a risk classification assigned by the lender at issuance — A being the safest and E the most risky. It factors in credit score, income, employment, and DTI. The question was whether the grade system actually predicted outcomes.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F903f8alecenbuymd58zi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F903f8alecenbuymd58zi.png" alt=" " width="587" height="221"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Formulas used:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Bad loan rate per grade
=AVERAGEIF($L$2:$L$1001,"A",$N$2:$N$1001)

-- Count per grade
=COUNTIF($L$2:$L$1001,"A")

-- Average credit score per grade
=AVERAGEIF($L$2:$L$1001,"A",$K$2:$K$1001)

-- Average interest rate per grade
=AVERAGEIF($L$2:$L$1001,"A",$E$2:$E$1001)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjavdu8ucw355o7w11dys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjavdu8ucw355o7w11dys.png" alt=" " width="419" height="295"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt; The grade system worked almost perfectly as a predictor. &lt;strong&gt;Grades A and B&lt;/strong&gt; — 380 loans combined — produced zero bad loans. &lt;strong&gt;Grade C&lt;/strong&gt; had just one charge-off out of 203. Then the cliff edge. &lt;strong&gt;Grade D&lt;/strong&gt; collapsed to 79% and &lt;strong&gt;Grade E&lt;/strong&gt; hit an absolute 100%. Not a single Grade E loan was repaid.&lt;br&gt;&lt;br&gt;
The &lt;strong&gt;most alarming detail&lt;/strong&gt; however is not the default rates — it's the interest rates. Despite Grade E borrowers defaulting at 100%, their average interest rate (15.22%) was barely higher than Grade A (14.82%). The lender identified the risk through grading but failed to price it accordingly. Riskier borrowers should carry significantly higher rates to compensate for expected losses.  &lt;/p&gt;
&lt;h4&gt;
  
  
  Finding 3 — Credit Score is the Single Strongest Default Predictor
&lt;/h4&gt;

&lt;p&gt;Credit score represents a borrower's creditworthiness based on their historical borrowing and repayment behavior. A band analysis was conducted by first creating a helper column:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Credit band helper column
=IFS(K2&amp;lt;600,"550-600",K2&amp;lt;650,"600-650",K2&amp;lt;700,"650-700",K2&amp;lt;750,"700-750",K2&amp;lt;=800,"750-800")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk57rc0q7ufyjmh5rlgqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk57rc0q7ufyjmh5rlgqz.png" alt=" " width="571" height="217"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Formulas used:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Bad loan rate per credit band
=AVERAGEIF($O$2:$O$1001,"550-600",$N$2:$N$1001)

-- Count per credit band
=COUNTIF($O$2:$O$1001,"550-600")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt; A credit score of &lt;strong&gt;650&lt;/strong&gt; functions as a near-perfect binary cutoff. &lt;strong&gt;Below 600&lt;/strong&gt; — every single borrower defaulted or was charged off. The &lt;strong&gt;600–650&lt;/strong&gt; band was nearly as bad at 76.7%. Cross 650 and the bad loan rate drops to exactly 0% — and stays there all the way to 800. No other variable in this dataset draws such a clean, decisive line between performing and non-performing loans. A hard underwriting rule requiring a minimum credit score of 650 would have eliminated the vast majority of bad loans in this portfolio.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Finding 4 — DTI Ratio is a Consistent Risk Escalator
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Debt-to-Income ratio&lt;/strong&gt; measures a borrower's monthly debt obligations as a percentage of their gross monthly income. The higher the DTI, the more financially stretched the borrower. A band analysis was conducted using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- DTI band helper column
=IFS(G2&amp;lt;=10,"0-10",G2&amp;lt;=20,"10-20",G2&amp;lt;=30,"20-30",G2&amp;lt;=40,"30-40",G2&amp;gt;40,"40+")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zjkx49a446x53unbm3c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zjkx49a446x53unbm3c.png" alt=" " width="560" height="174"&gt;&lt;/a&gt; &lt;br&gt;
&lt;strong&gt;Formulas used:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Bad loan rate per DTI band
=AVERAGEIF($P$2:$P$1001,"0-10",$N$2:$N$1001)

-- Average income per DTI band
=AVERAGEIF($P$2:$P$1001,"0-10",$F$2:$F$1001)  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8iekqs1psxnmhar90il4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8iekqs1psxnmhar90il4.png" alt=" " width="426" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt; Unlike credit score which produces a sharp binary cutoff, DTI tells a gradual story. As debt burden increases the bad loan rate climbs steadily — from 27.1% at the lowest band to 44.9% at 30–40%. Critically, average credit scores were nearly identical across all DTI bands (668–676), confirming that DTI and credit score measure different dimensions of risk. A borrower can have an acceptable credit score but still be dangerously overleveraged — and this portfolio shows overleveraging carries real consequences regardless of score. &lt;/p&gt;

&lt;h4&gt;
  
  
  Finding 5 — No Loan Purpose is Safe
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0x9p046g61ts7rx3b5x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0x9p046g61ts7rx3b5x.png" alt=" " width="536" height="236"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Formulas used:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Bad loan rate per purpose
=AVERAGEIF($J$2:$J$1001,"Medical",$N$2:$N$1001)

-- Bad loan count per purpose
=COUNTIFS($J$2:$J$1001,"Medical",$N$2:$N$1001,1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt; Across all six loan purposes bad loan rates ranged from &lt;strong&gt;34.8% to 40.8%&lt;/strong&gt; — a narrow 6 percentage point band.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Medical loans&lt;/strong&gt; carried the highest risk, likely because borrowers taking medical loans are often already under financial stress at application. The narrow spread means loan purpose alone cannot be used to make reliable lending decisions. It needs to be combined with credit score and grade to add meaningful predictive value.  &lt;/p&gt;
&lt;h4&gt;
  
  
  Finding 6 — Home Ownership Adds Almost No Predictive Value
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frza6wzqzi9f7f8l4siq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frza6wzqzi9f7f8l4siq9.png" alt=" " width="555" height="148"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Formulas used:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=AVERAGEIF($I$2:$I$1001,"Rent",$N$2:$N$1001)
=AVERAGEIF($I$2:$I$1001,"Own",$N$2:$N$1001)
=AVERAGEIF($I$2:$I$1001,"Mortgage",$N$2:$N$1001)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt; The spread between all three groups is just &lt;strong&gt;4.7&lt;/strong&gt; percentage points. Counterintuitively, outright homeowners performed worst of the three — directly challenging the conventional lending assumption that homeownership signals financial stability. In isolation home ownership is not a reliable risk indicator in this portfolio and should never be used as a standalone lending criterion.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Finding 7 — The Portfolio Has Been Deteriorating Since 2021
&lt;/h4&gt;

&lt;p&gt;The trend analysis used the Year helper column combined with &lt;strong&gt;COUNTIFS&lt;/strong&gt; and &lt;strong&gt;AVERAGEIFS&lt;/strong&gt; to evaluate performance year over year.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2fyq8814n8fqtgl38ei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2fyq8814n8fqtgl38ei.png" alt=" " width="580" height="259"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Formulas used:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Loan count per year
=COUNTIF($O$2:$O$1001,A2)

-- Total volume per year
=SUMIF($O$2:$O$1001,A2,$D$2:$D$1001)

-- Bad loan rate per year
=AVERAGEIF($O$2:$O$1001,A2,$N$2:$N$1001)

-- Fully paid % per year
=COUNTIFS($O$2:$O$1001,A2,$M$2:$M$1001,"Fully Paid")/COUNTIF($O$2:$O$1001,A2)

-- Year over year bad rate change
=IFERROR((C3-C2)/C2,"-")  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fignguf2w0m3pref922fn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fignguf2w0m3pref922fn.png" alt=" " width="485" height="293"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt; &lt;strong&gt;2021&lt;/strong&gt; was the portfolio's strongest year — lowest &lt;strong&gt;bad loan rate&lt;/strong&gt; (33.3%), highest &lt;strong&gt;fully paid rate&lt;/strong&gt; (66.7%), and highest average credit score (682). From 2022 onwards the portfolio deteriorated consistently. By &lt;strong&gt;2023&lt;/strong&gt; the &lt;strong&gt;bad loan rate&lt;/strong&gt; hit 41.5% — the worst in the entire dataset — with the &lt;strong&gt;default rate&lt;/strong&gt; alone reaching 24.5%, the highest single year figure across all six years. Average credit scores in 2022 and 2023 dropped back to 666, almost identical to 2018 levels. This pattern strongly suggests underwriting standards loosened after 2021.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Finding 8 — Grade D and Grade E Fail Differently
&lt;/h4&gt;

&lt;p&gt;The &lt;strong&gt;cross-tabulation&lt;/strong&gt; was built using a single &lt;strong&gt;COUNTIFS&lt;/strong&gt; formula written once and dragged across the entire table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Core cross-tabulation formula
=COUNTIFS($L$2:$L$1001,$A3,$M$2:$M$1001,B$2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;$A3&lt;/strong&gt; locks the column but lets the row move. &lt;strong&gt;B$2&lt;/strong&gt; locks the row but lets the column move — allowing the formula to be written once and dragged across all grade and status combinations automatically.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksvykvyal76pmmy6x3fi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksvykvyal76pmmy6x3fi.png" alt=" " width="569" height="245"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;% Breakdown (referencing count table):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;-- % of row total&lt;br&gt;
=B3/$E3&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff64dvce3fg45o10xfoyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff64dvce3fg45o10xfoyr.png" alt=" " width="555" height="217"&gt;&lt;/a&gt;   &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this tells us:&lt;/strong&gt; Both &lt;strong&gt;Grade D and E&lt;/strong&gt; record 100% bad loan rates but fail in completely different ways. &lt;strong&gt;Grade D&lt;/strong&gt; loans predominantly &lt;strong&gt;charge off&lt;/strong&gt; at 72.2% — the lender writes the debt off as unrecoverable in nearly three quarters of cases.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Grade E&lt;/strong&gt; flips this pattern — 89.2% &lt;strong&gt;default&lt;/strong&gt; while only 10.8% &lt;strong&gt;charge off&lt;/strong&gt;, meaning the lender still pursues recovery on most Grade E failures. Since charge-offs represent total losses while defaults leave some recovery options open, Grade D is arguably more damaging to the lender than Grade E despite both recording identical bad loan rates.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Recommendations
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enforce a Hard Credit Score Floor of 650&lt;/strong&gt;
The data is unambiguous. No borrower above 650 defaulted. No borrower below 600 repaid. Implementing a minimum credit score of 650 as a hard underwriting rule would eliminate the vast majority of bad loans. 577 of 1,000 loans already sit above this threshold — meaning this rule would not dramatically reduce origination volume while significantly improving portfolio quality.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restrict Origination to Grades A, B, and C&lt;/strong&gt;
Grades A, B, and C combined produced just one bad loan out of 583. Grades D and E produced 374 bad loans out of 417. Concentrating origination in the top three grades while either eliminating or dramatically repricing Grades D and E would transform this portfolio's performance. At minimum, Grade D and E interest rates need to reflect the actual level of risk — not sit within 0.5% of Grade A rates.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Investigate and Address the Post-2021 Deterioration&lt;/strong&gt;
The consistent worsening of bad loan rates from 2021 to 2023 — combined with declining average credit scores — points to a loosening of underwriting standards in recent years. The 2023 default rate of 24.5% is the highest in the dataset. Without intervention the trajectory points toward a 2024 bad loan rate exceeding 41.5%. Understanding what changed in underwriting policy after 2021 is the most urgent question this portfolio raises.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This analysis set out to answer one question — what does the data tell us about why loans go bad? The answer turned out to be surprisingly clean.   Two variables dominate everything else: &lt;strong&gt;credit score and loan grade&lt;/strong&gt;.   Both draw near-perfect lines between performing and non-performing loans. DTI adds a secondary layer of independent risk. Everything else — purpose, home ownership, repayment period — contributes marginally at best.&lt;br&gt;&lt;br&gt;
The broader lesson for any data analyst working in financial risk is this: averages deceive, segmentation reveals. The average borrower in this portfolio looks reasonable — $82,924 income, 672 credit score, 9.8 years employed.&lt;br&gt;&lt;br&gt;
But segment by grade and credit score and the picture changes completely. The risk is not spread evenly across the portfolio. It is concentrated, identifiable, and largely predictable — which means it is also largely preventable.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Dataset sourced from a financial risk portfolio simulation&lt;/em&gt;.&lt;br&gt;
Here is the Dataset: &lt;a href="https://docs.google.com/spreadsheets/d/11brWqBDJMNOemNAwGP6rI7kzAcyRGq8e/edit?usp=sharing&amp;amp;ouid=103314870338754690127&amp;amp;rtpof=true&amp;amp;sd=true" rel="noopener noreferrer"&gt;Financial Dataset&lt;/a&gt;&lt;/p&gt;

</description>
      <category>excel</category>
      <category>analytics</category>
      <category>microsoft365</category>
      <category>visualisation</category>
    </item>
    <item>
      <title>Mastering DAX in Power BI: A Beginner’s Guide</title>
      <dc:creator>Maurine Nyongesa</dc:creator>
      <pubDate>Sun, 10 Nov 2024 00:27:12 +0000</pubDate>
      <link>https://dev.to/maurine/mastering-dax-in-power-bi-a-beginners-guide-3cpd</link>
      <guid>https://dev.to/maurine/mastering-dax-in-power-bi-a-beginners-guide-3cpd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. What is DAX?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DAX&lt;/strong&gt; (Data Analysis Expressions) is the formula language used in Power BI, Excel Power Pivot, and SQL Server Analysis (&lt;strong&gt;SSAS&lt;/strong&gt;). It is designed to handle data manipulation and computations, allowing for powerful data models and analysis.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example Scenario:&lt;/strong&gt; Imagine you have a dataset of retail transactions. You want to calculate total sales, profit margin, or year-over-year growth. DAX enables you to write formulas that generate these values dynamically, adapting to filters and user selections in your reports.&lt;br&gt;&lt;br&gt;
It plays a &lt;strong&gt;vital role&lt;/strong&gt; in enhancing the reporting and analysis capabilities of Power BI, enabling users to dive deeper into their data by creating custom insights.&lt;br&gt;&lt;br&gt;
DAX is the &lt;strong&gt;primary used for&lt;/strong&gt; creating calculated columns, calculated measures and managing relationships between data tables.&lt;br&gt;&lt;br&gt;
This guide introduces essential DAX functions and concepts to get you started with creating powerful calculations in Power BI.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Essential DAX Concepts and Functions
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Calculated Columns vs. Measures
&lt;/h4&gt;

&lt;p&gt;Understanding the difference between calculated columns and measures is crucial when working with DAX:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calculated Columns:&lt;/strong&gt; These are computed row-by-row and added to your data model as new columns. They are useful for creating static calculations.&lt;/p&gt;

&lt;p&gt;Example: Calculating a Profit column in the Sales table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Profit = Sales[Revenue] - Sales[Cost]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Measures:&lt;/strong&gt; Measures are dynamic calculations that aggregate based on the current filter context, which means they change based on the data you view in your reports. Measures are great for calculations like sums, averages, and ratios.&lt;/p&gt;

&lt;p&gt;Example: Calculating total sales as a measure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Total Sales = SUM(Sales[Amount])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Key DAX Functions Categories with examples
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.1 Aggregate Functions:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;SUM:&lt;/strong&gt; Adds up all the values in a specific column.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt; This DAX formula calculates the total sales amount from the SalesAmount column of the Sales table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Total Sales = SUM(Sales[SalesAmount])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AVERAGE:&lt;/strong&gt; Returns the average of all values in a column.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Average Sales = AVERAGE(Sales[SalesAmount])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This computes the average sales amount for all rows in the Sales table.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;COUNT:&lt;/strong&gt; Counts the number of non-blank cells in a column.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Number of products = COUNT(Products[ProductID])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This counts the number of non-empty ProductID entries in the Products table.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;SUMX&lt;/strong&gt;: This performs row-by-row calculations for each record in a table and then returns the total sum of these calculations.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Total Revenue = SUMX(Sales, Sales[Quantity] * Sales[UnitPrice])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This formula multiplies Quantity by UnitPrice for each row and sums the result across all rows.  &lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Filter Funtions:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CALCULATE:&lt;/strong&gt; Modifies the filter context of an expression, allowing you to customize the filters applied to your calculations.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Sales in West = CALCULATE(SUM(Sales[Amount]), Sales[Region] = "West")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This calculates the total sales only for the west region, regardless of any other filters applied.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;FILTER:&lt;/strong&gt; Returns a table containing only rows that satisfy a given condition.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Expensive Products = FILTER(Products, Products[Price] &amp;gt; 100)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This filters out products that cost more than 100, returning only those rows.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;ALL:&lt;/strong&gt; Ignores any filters that might be applied to a column or table.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Total Sales All Regions = CALCULATE(SUM(Sales[SalesAmount]), ALL(Sales[Region]))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This calculates the total sales without considering any filters on the Region column.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;RELATED:&lt;/strong&gt; Retrieves values from a related tables using relationships.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Product Name = RELATED(Products[ProductName])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pulls the product name from the Products table into the Sales table, assuming a relationship exists between the two tables.  &lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Time Intelligence Functions:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;SAMPLEPERIODLASTYEAR:&lt;/strong&gt; Compare data from the same period in the previous year.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Sales Last Year = CALCULATE(SUM(Sales[SalesAmount]),SAMPLEPERIODLASTYEAR(Sales[Date]))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This formula calculates the total sales for the same period last year.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;TOTALYTD&lt;/strong&gt;: Calculates the year-to-date total measure.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; YTD Sales = TOTALYTD(SUM(Sales[SalesAmount]), Sales[Date])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives the total sales from the beginning of the year to the current date.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;DATEADD&lt;/strong&gt;: Shifts dates in a date column by a specified number of days, months, or years.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Sales Previous Month = CALCULATE(SUM(Sales[SalesAmount]),  DATEADD(Sales[Date], -1, MONTH))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This moves the date back by one month and calculates the sales for that period.  &lt;/p&gt;

&lt;h3&gt;
  
  
  3.4 Logical Functions:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;IF&lt;/strong&gt;: Evaluates a condition and returns one values if the condition is TRUE and another if it is FALSE.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; SalesCategory = IF(SUM(Sales[SalesAmount] &amp;gt; 1000,"High","Low")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This classifies sales into "High" or "Low" categories based on whether the SalesAmount is greater than 1000&lt;br&gt;&lt;br&gt;
&lt;strong&gt;AND&lt;/strong&gt;: Returns TRUE if all conditions are TRUE&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Big Discount = IF(AND(Sales[Quality] &amp;gt; 50, Sales[Discount] &amp;gt; 10), "Yes","No")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This checks if both conditions (quantity greater than 50 and discount greater than 10 are met, then labels them "Yes" or "No".&lt;br&gt;&lt;br&gt;
&lt;strong&gt;OR&lt;/strong&gt;: Returns TRUE if atleast one conditions is TRUE&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Special Offer = IF(OR(Sales[Quality] &amp;gt; 100, Sales[Discount] &amp;gt; 20), "Special","Regular")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thsi checks if either quantity is greater than 200 or the discount is greater than 20.  &lt;/p&gt;

&lt;h3&gt;
  
  
  3.5 Text Functions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CONCATENATE&lt;/strong&gt;: Joins two or more strings into one.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Full Product Name = CONCATENATE(Products[ProductName],"-", Products[Category])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This joins the product name and category with a hyphen in between.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;UPPER&lt;/strong&gt;: Converts text to uppercase.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Upper Product Name = UPPER(Products[ProductName])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This converts the product name to uppercase.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;LEFT/RIGHT&lt;/strong&gt;: Extracts a specified number of characters from the left or right side of a text string.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Left Part of Name = LEFT(Products[ProductName], 5)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns the first 5 characters from the left of the product name.  &lt;/p&gt;

&lt;h3&gt;
  
  
  5.6 Mathematical Functions:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DIVIDE&lt;/strong&gt;: Performs division and handles division by zero.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;EXAMPLE&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Price Per Unit = DIVIDE(Sales[Amount], Sales[Quantity])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This calculates the price per unit, handling cases where the quantity might be zero.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;MOD&lt;/strong&gt;: Returns the remainder of a division operation.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Remainder = MOD(Products[Quantity],2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns the remainder when dividing the quantity by 2 (Useful for checking odd or even numbers)  &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;DAX provides a powerful set of functions that allow you to create dynamic, context-aware calculations in Power BI. By using aggregate, filter, time intelligence, and logical functions, you can craft precise and flexible reports and dashboards. It's essential to understand how these functions interact with your data model, especially in terms of context and relationships, to build complex and insightful calculations.&lt;/p&gt;

</description>
      <category>visualization</category>
      <category>powerbi</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Employee Management System Using SQL</title>
      <dc:creator>Maurine Nyongesa</dc:creator>
      <pubDate>Sun, 13 Oct 2024 09:44:48 +0000</pubDate>
      <link>https://dev.to/maurine/employee-management-system-using-sql-3nhd</link>
      <guid>https://dev.to/maurine/employee-management-system-using-sql-3nhd</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Employee Management System is an SQL-based project that streamlines managing employee and department data, tracks performance reviews, and generates insights through queries. It uses key SQL concepts like &lt;strong&gt;database creation, table relationships, joins&lt;/strong&gt;, and &lt;strong&gt;window functions&lt;/strong&gt; to analyze employee performance, salary, and department metrics. This system ensures efficient data management and provides insights for strategic HR decision-making.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Project Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database Creation&lt;/strong&gt;: employee_management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tables&lt;/strong&gt; &lt;br&gt;
      &lt;strong&gt;departments:&lt;/strong&gt; Stores information about departments (name, location).&lt;br&gt;
      &lt;strong&gt;employees:&lt;/strong&gt; Stores employee data (personal details, hire date, salary, job title, department).&lt;br&gt;
     &lt;strong&gt;performance_reviews:&lt;/strong&gt; Tracks performance reviews with ratings and comments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Database Creation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We begin by creating the &lt;strong&gt;employee_management&lt;/strong&gt; database, which stores employee, department, and performance review data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- CREATING DATABASE
CREATE DATABASE employee_management;
USE employee_management;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Table Creation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Next, we create three tables: &lt;strong&gt;departments, employees&lt;/strong&gt;, and &lt;strong&gt;performance_reviews&lt;/strong&gt;, each linked via foreign keys to model relationships between employees, their departments, and performance reviews.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- CREATING TABLES
CREATE TABLE departments(
    department_id INT PRIMARY KEY AUTO_INCREMENT,
    department_name VARCHAR(50) NOT NULL,
    location VARCHAR(100)
);

CREATE TABLE employees(
    employee_id INT PRIMARY KEY AUTO_INCREMENT,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE,
    hire_date DATE NOT NULL,
    salary DECIMAL(10,2),
    department_id INT,
    job_title VARCHAR(50),
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

CREATE TABLE performance_reviews(
    review_id INT PRIMARY KEY AUTO_INCREMENT,
    employee_id INT,
    review_date DATE NOT NULL,
    rating INT CHECK (rating BETWEEN 1 AND 5),
    comments TEXT,
    FOREIGN KEY (employee_id) REFERENCES employees(employee_id)
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Data Insertion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once the tables are created, we can insert sample data into the departments, employees, and performance_reviews tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- INSERTING DATA
-- Departments Table
INSERT INTO departments(department_name, location) VALUES
    ('Sales', 'New York'),
    ('HR', 'Los Angeles'),
    ('IT', 'San Francisco');

-- Employees Table
INSERT INTO employees(first_name, last_name, email, hire_date, salary, department_id, job_title)
VALUES
    ('Maurine', 'Nyongesa', 'maurine.nyongesa@gmail.com', '2021-03-15', 55000, 1, 'Sales Executive'),
    ('Asa', 'Moh', 'asa.moh@gmail.com', '2020-06-30', 60000, 2, 'HR Manager'),
    ('Steve', 'Jobs', 'steve.jobs@gmail.com', '2019-08-10', 75000, 3, 'IT Specialist');

-- Performance Reviews Table
INSERT INTO performance_reviews(employee_id, review_date, rating, comments) VALUES
    (1, '2023-06-15', 4, 'Great performance but needs improvement in client interaction.'),
    (2, '2023-05-12', 5, 'Excellent management skills, highly recommended for promotion.'),
    (3, '2023-07-20', 3, 'Satisfactory performance but needs more technical training.');

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Querying Data&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Below are SQL queries used to retrieve, update, and analyze the data in the Employee Management System.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Queries&lt;/strong&gt;&lt;br&gt;
Retrieve all employee details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM employees;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update an employee's salary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UPDATE employees
SET salary = 65000
WHERE employee_id = 1;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a new employee:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSERT INTO employees (first_name, last_name, email, hire_date, salary, job_title, department_id)
VALUES ('Jane', 'Doe', 'jane.doe@email.com', '2023-05-15', 55000, 'Marketing Specialist', 2);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Advanced Queries&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Joining Tables:&lt;/strong&gt; Retrieve all employees with their department names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT e.first_name, e.last_name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Salary Analysis:&lt;/strong&gt; Find employees with a salary above 60,000.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT first_name, last_name
FROM employees
WHERE salary &amp;gt; 60000;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Performance Review:&lt;/strong&gt; Retrieve performance reviews for a specific employee.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT e.first_name, e.last_name, p.review_date, p.rating, p.comments
FROM employees e
JOIN performance_reviews p ON e.employee_id = p.employee_id
WHERE e.employee_id = 1;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Salary Analysis by Department:&lt;/strong&gt; Calculate the average salary for each department&lt;br&gt;
This Query the average salary for each department and shows it alongside each employee's information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT AVG(e.salary) AS average_salary, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Employee Ranking by Salary:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT first_name, last_name, salary,
       RANK() OVER (ORDER BY salary) AS salary_rank
FROM employees;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cumulative Salary:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT first_name, last_name, salary,
       SUM(salary) OVER (ORDER BY salary) AS cumulative_salary
FROM employees;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Row Number Based on Hire Date:&lt;/strong&gt;&lt;br&gt;
This assigns a row number to each employee, sorted by the date they were hired.&lt;br&gt;
 It’s useful for scenarios where you want to track the order of employee hiring.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT first_name, last_name, hire_date,
       ROW_NUMBER() OVER (ORDER BY hire_date) AS row_num
FROM employees;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Performance Review Trend using Lead and Lag Functions:&lt;/strong&gt;&lt;br&gt;
This query shows an employee's current review rating along with the previous and next ratings (if they exist).&lt;br&gt;
It uses the &lt;strong&gt;LAG() function&lt;/strong&gt; to pull the previous review and &lt;strong&gt;LEAD()&lt;/strong&gt; to pull the next review, within the same employee’s records&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT employee_id, review_date, rating,
       LAG(rating) OVER (PARTITION BY employee_id ORDER BY review_date) AS prev_rating,
       LEAD(rating) OVER (PARTITION BY employee_id ORDER BY review_date) AS next_rating
FROM performance_reviews;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Percentile Ranking of Salaries:&lt;/strong&gt;&lt;br&gt;
This query calculates the percentile rank of each employee’s salary compared to others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT first_name, last_name, salary,
       PERCENT_RANK() OVER (ORDER BY salary) AS percent_rank_salary
FROM employees;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Employee Management System&lt;/strong&gt; demonstrates how SQL can be leveraged to efficiently manage and analyze employee and department data. By utilizing core SQL concepts such as database creation, table relationships, and advanced queries like window functions and joins, this system offers valuable insights into employee performance, salary distributions, and department metrics. This project showcases the powerful capabilities of SQL in organizing and extracting data, aiding &lt;br&gt;
in data-driven decision-making for HR and management.&lt;br&gt;
You can explore more of my work on &lt;a href="https://www.linkedin.com/in/maurine-nyongesa-4ab607224/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;and find the complete repository for this Employee Management System project on &lt;a href="https://github.com/M-aurine" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>datascience</category>
      <category>sqlserver</category>
    </item>
  </channel>
</rss>
