<?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: David Gitonga</title>
    <description>The latest articles on DEV Community by David Gitonga (@david_gitonga_2983).</description>
    <link>https://dev.to/david_gitonga_2983</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4070899%2Fae6d0be0-1f9d-4832-8438-4fb66df1c6bc.jpg</url>
      <title>DEV Community: David Gitonga</title>
      <link>https://dev.to/david_gitonga_2983</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/david_gitonga_2983"/>
    <language>en</language>
    <item>
      <title># SQL for Data Analysis: Window Functions, Joins, CTEs and Subqueries</title>
      <dc:creator>David Gitonga</dc:creator>
      <pubDate>Fri, 16 Oct 2026 17:46:49 +0000</pubDate>
      <link>https://dev.to/david_gitonga_2983/-sql-for-data-analysis-window-functions-joins-ctes-and-subqueries-m51</link>
      <guid>https://dev.to/david_gitonga_2983/-sql-for-data-analysis-window-functions-joins-ctes-and-subqueries-m51</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As I continue learning SQL for data analysis, I have come across some concepts that help answer more complex questions than basic &lt;code&gt;SELECT&lt;/code&gt;, &lt;code&gt;WHERE&lt;/code&gt;, and &lt;code&gt;GROUP BY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I will explain four of them using examples from a hospital dataset: Window Functions, Joins, Common Table Expressions (CTEs), and Subqueries.&lt;/p&gt;

&lt;p&gt;The goal is to understand what each one does and when to use it in a real situation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The examples use assumed table and column names. They may need to be adjusted to match the actual hospital dataset.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. SQL Window Functions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What are Window Functions?
&lt;/h3&gt;

&lt;p&gt;Window functions allow us to calculate values across related rows without removing the individual records.&lt;/p&gt;

&lt;p&gt;For example, a hospital analyst may want to rank patients by billing amount while still seeing each patient's record.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Syntax
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TotalBilling&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OVER()&lt;/code&gt; tells SQL which set of rows to use for the calculation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PARTITION BY&lt;/code&gt; divides rows into groups.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ORDER BY&lt;/code&gt; determines the order of rows.&lt;/li&gt;
&lt;li&gt;A window frame determines which rows are included in a calculation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of a running total:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;VisitID&lt;/span&gt;
    &lt;span class="k"&gt;ROWS&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="n"&gt;UNBOUNDED&lt;/span&gt; &lt;span class="k"&gt;PRECEDING&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;CURRENT&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds the current bill to all the preceding bills in the specified order.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ranking Functions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. ROW_NUMBER()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Assigns a unique number to each row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;ROW_NUMBER&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
    &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;VisitDate&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This numbers each patient's visits from earliest to latest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. RANK()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ranks records and gives tied values the same rank, leaving gaps afterward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;RANK&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ranks hospital bills from highest to lowest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. DENSE_RANK()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Works like &lt;code&gt;RANK()&lt;/code&gt;, but does not leave gaps between ranks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;DENSE_RANK&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful when ranking patients or departments by billing amount.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. NTILE()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Divides ordered records into approximately equal groups.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;NTILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This divides billing records into four groups for cost analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigation Functions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;5. LAG()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Returns a value from a previous row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;LAG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VisitDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
    &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;VisitDate&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps identify a patient's previous visit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. LEAD()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Returns a value from a following row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;LEAD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VisitDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
    &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;VisitDate&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps compare a visit with the next recorded visit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. FIRST_VALUE()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Returns the first value in the specified window.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;FIRST_VALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VisitDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
    &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;VisitDate&lt;/span&gt;
    &lt;span class="k"&gt;ROWS&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="n"&gt;UNBOUNDED&lt;/span&gt; &lt;span class="k"&gt;PRECEDING&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;UNBOUNDED&lt;/span&gt; &lt;span class="k"&gt;FOLLOWING&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This identifies the first recorded visit for each patient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. LAST_VALUE()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Returns the last value within the specified window frame.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;LAST_VALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VisitDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
    &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;VisitDate&lt;/span&gt;
    &lt;span class="k"&gt;ROWS&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="n"&gt;UNBOUNDED&lt;/span&gt; &lt;span class="k"&gt;PRECEDING&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;UNBOUNDED&lt;/span&gt; &lt;span class="k"&gt;FOLLOWING&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This displays the latest recorded visit date for each patient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aggregate Window Functions
&lt;/h3&gt;

&lt;p&gt;These functions calculate values across rows.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Hospital example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SUM()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Adds values&lt;/td&gt;
&lt;td&gt;Total billing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AVG()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Calculates the average&lt;/td&gt;
&lt;td&gt;Average bill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;COUNT()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Counts rows or values&lt;/td&gt;
&lt;td&gt;Number of visits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MIN()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Finds the smallest value&lt;/td&gt;
&lt;td&gt;Lowest bill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MAX()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Finds the largest value&lt;/td&gt;
&lt;td&gt;Highest bill&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;AverageBill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This displays each bill alongside the average bill across the dataset.&lt;/p&gt;

&lt;p&gt;The main difference between a normal aggregate and a window aggregate is that &lt;code&gt;GROUP BY&lt;/code&gt; usually reduces records to one row per group, while a window function keeps the individual rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. SQL Joins
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What are Joins?
&lt;/h3&gt;

&lt;p&gt;Hospital data is usually stored in different tables. For example, patient details may be in &lt;code&gt;Patients&lt;/code&gt;, visits in &lt;code&gt;Visits&lt;/code&gt;, and charges in &lt;code&gt;Billing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Joins allow us to combine related records using a common column.&lt;/p&gt;

&lt;h3&gt;
  
  
  INNER JOIN
&lt;/h3&gt;

&lt;p&gt;Returns only matching records from both tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this when you only need visits with matching billing records.&lt;/p&gt;

&lt;h3&gt;
  
  
  LEFT JOIN
&lt;/h3&gt;

&lt;p&gt;Returns all records from the left table and matching records from the right.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Patients&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This includes patients who have never visited the hospital. Their visit columns will contain &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  RIGHT JOIN
&lt;/h3&gt;

&lt;p&gt;Returns all records from the right table and matching records from the left.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BillID&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="k"&gt;RIGHT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful when every billing record must appear, even if a matching visit is missing.&lt;/p&gt;

&lt;h3&gt;
  
  
  FULL OUTER JOIN
&lt;/h3&gt;

&lt;p&gt;Returns matching and unmatched records from both tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BillID&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="k"&gt;FULL&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can help identify missing links during a billing audit. Note that MySQL does not directly support &lt;code&gt;FULL OUTER JOIN&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  CROSS JOIN
&lt;/h3&gt;

&lt;p&gt;Returns every possible combination of rows from two tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShiftName&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Departments&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
&lt;span class="k"&gt;CROSS&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Shifts&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can help generate department and shift combinations for staffing plans.&lt;/p&gt;

&lt;h3&gt;
  
  
  SELF JOIN
&lt;/h3&gt;

&lt;p&gt;Joins a table to itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoctorName&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;Doctor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoctorName&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;Manager&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Doctors&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Doctors&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ManagerID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoctorID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This displays each doctor alongside their manager.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Join&lt;/th&gt;
&lt;th&gt;Main purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only matching records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All left-side records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RIGHT JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All right-side records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FULL OUTER JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All records from both sides&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CROSS JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Every combination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SELF JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Relate records in the same table&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One thing I have learned is that joins can increase the number of rows when multiple records match. This is important when calculating billing totals because careless joins can duplicate amounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Common Table Expressions (CTEs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a CTE?
&lt;/h3&gt;

&lt;p&gt;A CTE is a named query result created using &lt;code&gt;WITH&lt;/code&gt;. It makes complex SQL easier to read by breaking it into smaller steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic CTE
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;PatientBilling&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt;
        &lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TotalBilling&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;PatientBillingData&lt;/span&gt;
    &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;PatientBilling&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;TotalBilling&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This calculates each patient's total billing and then returns patients whose total exceeds 5,000. &lt;code&gt;PatientBillingData&lt;/code&gt; is an illustrative table name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple CTEs
&lt;/h3&gt;

&lt;p&gt;We can define more than one CTE when a problem requires several calculations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;VisitCounts&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TotalVisits&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt;
    &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;BillingTotals&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TotalBilling&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
        &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitID&lt;/span&gt;
    &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;vc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TotalVisits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TotalBilling&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;VisitCounts&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;vc&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;BillingTotals&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;bt&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;vc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first CTE counts visits, the second calculates billing totals, and the final query combines them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recursive CTEs
&lt;/h3&gt;

&lt;p&gt;Recursive CTEs reference their own results to work through hierarchical data, such as a hospital's doctor-manager structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="k"&gt;RECURSIVE&lt;/span&gt; &lt;span class="n"&gt;DoctorHierarchy&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;DoctorID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DoctorName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ManagerID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;Level&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Doctors&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ManagerID&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;

    &lt;span class="k"&gt;UNION&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt;

    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoctorID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoctorName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ManagerID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;Level&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Doctors&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
    &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;DoctorHierarchy&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;dh&lt;/span&gt;
        &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ManagerID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoctorID&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;DoctorHierarchy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part identifies the top-level doctors. The recursive part finds the doctors reporting to them and continues through the hierarchy.&lt;/p&gt;

&lt;p&gt;This syntax is for PostgreSQL and other databases supporting &lt;code&gt;WITH RECURSIVE&lt;/code&gt;. SQL Server uses different recursive CTE syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  CTEs with Joins and Aggregations
&lt;/h3&gt;

&lt;p&gt;CTEs can summarize data before joining it to another table.&lt;/p&gt;

&lt;p&gt;For example, we can calculate department billing using &lt;code&gt;SUM()&lt;/code&gt; and &lt;code&gt;GROUP BY&lt;/code&gt;, then join the result to a department table to display department names and totals.&lt;/p&gt;

&lt;h3&gt;
  
  
  CTEs vs Subqueries
&lt;/h3&gt;

&lt;p&gt;A subquery is a query inside another query. A CTE gives a query a name before the main query uses it.&lt;/p&gt;

&lt;p&gt;Both can solve similar problems, but CTEs often make long queries easier to understand and maintain. Neither is automatically faster; performance depends on the database and execution plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. SQL Subqueries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a Subquery?
&lt;/h3&gt;

&lt;p&gt;A subquery is a query placed inside another SQL query. It helps us use the result of one calculation to answer another question.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scalar Subquery
&lt;/h3&gt;

&lt;p&gt;Returns one value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns bills that are higher than the average bill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-Correlated Subquery
&lt;/h3&gt;

&lt;p&gt;Runs independently of the outer query because it does not reference the outer query's columns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Doctors&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Cardiology'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This finds visits in a department returned by the inner query.&lt;/p&gt;

&lt;h3&gt;
  
  
  Correlated Subquery
&lt;/h3&gt;

&lt;p&gt;References a column from the outer query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientName&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Patients&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns patients who have at least one visit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested Subquery
&lt;/h3&gt;

&lt;p&gt;A subquery placed inside another subquery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="k"&gt;HAVING&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TotalAmount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TotalAmount&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
        &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;PatientTotals&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example assumes billing records contain &lt;code&gt;PatientID&lt;/code&gt;. It compares each patient's total billing with the average of patient-level totals.&lt;/p&gt;

&lt;h3&gt;
  
  
  IN
&lt;/h3&gt;

&lt;p&gt;Checks whether a value matches any value returned by a subquery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Doctors&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Cardiology'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This finds visits in Cardiology when that department is present in the doctor records.&lt;/p&gt;

&lt;h3&gt;
  
  
  EXISTS
&lt;/h3&gt;

&lt;p&gt;Checks whether a subquery returns at least one row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Patients&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Visits&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns patients with recorded visits.&lt;/p&gt;

&lt;h3&gt;
  
  
  ANY
&lt;/h3&gt;

&lt;p&gt;The comparison needs to be true for at least one value returned by the subquery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;ANY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This finds bills that exceed at least one bill below 5,000.&lt;/p&gt;

&lt;h3&gt;
  
  
  ALL
&lt;/h3&gt;

&lt;p&gt;The comparison must be true for every value returned by the subquery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This finds bills that exceed every bill below 5,000.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subqueries in SELECT, FROM and WHERE
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;In SELECT:&lt;/strong&gt; Add a calculated value to each row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;AverageBill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In FROM:&lt;/strong&gt; Create a derived table that can be queried.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TotalBilling&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TotalBilling&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
    &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;PatientID&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;PatientTotals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In WHERE:&lt;/strong&gt; Filter records based on another query's result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;VisitID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Billing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main difference is where the result of the subquery is used: as a selected value, as a dataset, or as a filtering condition.&lt;/p&gt;

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

&lt;p&gt;These four SQL concepts help me move beyond basic queries and answer more practical data analysis questions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Window functions help with ranking, comparisons, and calculations across rows.&lt;/li&gt;
&lt;li&gt;Joins bring related data together from different tables.&lt;/li&gt;
&lt;li&gt;CTEs make complex queries easier to organize.&lt;/li&gt;
&lt;li&gt;Subqueries allow one query to use the results of another.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For me, the important part is not just memorizing the syntax. It is understanding the problem first and choosing the SQL technique that solves it.&lt;/p&gt;

&lt;p&gt;As I continue working with hospital data, these concepts will help me analyse patient visits, billing, department activity, and missing records more effectively.&lt;/p&gt;

&lt;h1&gt;
  
  
  SQL #DataAnalytics #DataAnalysis #Database #LearningInPublic
&lt;/h1&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>analytics</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Building an Interactive Excel Dashboard for E-commerce Product Analysis , A Jumia case Study</title>
      <dc:creator>David Gitonga</dc:creator>
      <pubDate>Sat, 05 Sep 2026 14:19:46 +0000</pubDate>
      <link>https://dev.to/david_gitonga_2983/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-jumia-case-study-1gnm</link>
      <guid>https://dev.to/david_gitonga_2983/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-jumia-case-study-1gnm</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;For my first data analytics project, I have had the chance to work with a Jumia products dataset and used &lt;strong&gt;Excel&lt;/strong&gt; to turn the raw data into something that could actually be used to understand product performance.&lt;/p&gt;

&lt;p&gt;The main goal of the project was not just to clean it and make a pretty dashboard. I wanted to use the data to answer some simple questions about product pricing, discounts, ratings and reviews.&lt;/p&gt;

&lt;p&gt;some of the questions answered within the project were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do products with bigger discounts get more reviews?&lt;/li&gt;
&lt;li&gt;Do highly rated products get more engagements?&lt;/li&gt;
&lt;li&gt;Is there a relationship between price and rating?&lt;/li&gt;
&lt;li&gt;Which products have the highest rating and reviews?&lt;/li&gt;
&lt;li&gt;which products might need better pricing or marketing strategies?
This project also gave me a chance to practice some of the basic data analytics skill I have been learning, especially &lt;strong&gt;data cleaning, Excel formulas, PivotTables, Charts and Dashboard creation&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  THE DATASET
&lt;/h2&gt;

&lt;p&gt;The dataset contains products information from Jumia. The main columns I worked with were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product&lt;/li&gt;
&lt;li&gt;Current price&lt;/li&gt;
&lt;li&gt;Old price&lt;/li&gt;
&lt;li&gt;Discount&lt;/li&gt;
&lt;li&gt;Review &lt;/li&gt;
&lt;li&gt;Rating
The data was not completely ready for analysis, so I first had to inspect it and make some changes before building the dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One important thing I kept in mind is that &lt;strong&gt;reviews are being used as a measure of engagement, not as actual sales data.&lt;/strong&gt; A product having more reviews does not automatically mean its more products.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Raw Data
&lt;/h2&gt;

&lt;p&gt;I started by creating a &lt;strong&gt;Raw_Data&lt;/strong&gt; sheet.&lt;/p&gt;

&lt;p&gt;I kept this sheet as the original version of the dataset so that I could always go back to the starting point if something went wrong during cleaning.&lt;/p&gt;

&lt;p&gt;While checking the data, I noticed some issues such as &lt;strong&gt;duplicate records, price stored with currency text, price range and some missing reviews and rating values.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also found some products that appeared more than once with exactly the same information. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cleaning the Data
&lt;/h2&gt;

&lt;p&gt;After checkinh the raw dat, I created a &lt;strong&gt;Cleaned_Data&lt;/strong&gt; sheet.&lt;br&gt;
The main cleaning steps include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing exact duplicate records.
-Working with the price fields so the be used for calculations&lt;/li&gt;
&lt;li&gt;Making sure discount values could be used in calculation&lt;/li&gt;
&lt;li&gt;Checking rating and review values&lt;/li&gt;
&lt;li&gt;Keeping missing values blank instead of automatically treating them as zero&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also added some calculated fields that would help with the analysis.&lt;/p&gt;

&lt;p&gt;One of them was &lt;strong&gt;Discount Amount&lt;/strong&gt;,which shows the difference between the old price and current price.&lt;br&gt;
For example:&lt;br&gt;
&lt;code&gt;=old price-Current Price&lt;/code&gt;&lt;br&gt;
I also used categories to make some of the analysis easier to understand, such as rating categories, discount categories and price categories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Excel for the Analysis
&lt;/h2&gt;

&lt;p&gt;once the data was prepared, i moved on to the analysis section.&lt;br&gt;
I calculated some of the basics statistics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total number of products&lt;/li&gt;
&lt;li&gt;Average current price&lt;/li&gt;
&lt;li&gt;Average old price&lt;/li&gt;
&lt;li&gt;Average discount&lt;/li&gt;
&lt;li&gt;Average rating&lt;/li&gt;
&lt;li&gt;Total reviews&lt;/li&gt;
&lt;li&gt;Highest product price&lt;/li&gt;
&lt;li&gt;Lowest product price
I also used correlation to look at the relationship between some of the variables.
which I looked at:
&lt;strong&gt;Discount vs Reviews&lt;/strong&gt;
&lt;strong&gt;Rating vs Reviews&lt;/strong&gt;
&lt;strong&gt;Current Price vs Rating&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The purpose was to see whether there was a noticeable relationship between these variables.&lt;br&gt;
However, correlation doesn't mean that one variable caused another. It only helps show whether two variables tend to move together.&lt;/p&gt;

&lt;h2&gt;
  
  
  PivotTables and Charts
&lt;/h2&gt;

&lt;p&gt;After the calculation, I created PivoTables to make it easier to summarize the data.&lt;br&gt;
Some of the PivotTables looked at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rating categories&lt;/li&gt;
&lt;li&gt;Discount categories&lt;/li&gt;
&lt;li&gt;Price categories&lt;/li&gt;
&lt;li&gt;Reviews by discount category&lt;/li&gt;
&lt;li&gt;Top products by rating&lt;/li&gt;
&lt;li&gt;Top products by reviews&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I then used these results to create charts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Dashboard
&lt;/h2&gt;

&lt;p&gt;The final step was putting the important information into or dashboard.&lt;br&gt;
I included KPI sections for things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total Products&lt;/li&gt;
&lt;li&gt;Average Price &lt;/li&gt;
&lt;li&gt;Average Discount&lt;/li&gt;
&lt;li&gt;Average Rating&lt;/li&gt;
&lt;li&gt;Total Reviews&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also included charts for the different relationships I investigated and tables showing some of top-performing products.&lt;/p&gt;

&lt;p&gt;I added slicers so that the dashboard could be filtered by categories such as &lt;strong&gt;Rating category, Discount Category and price category.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Overall, this project was a good way for me to practice the basic data analytics process using Excel.&lt;/p&gt;

&lt;p&gt;I started with raw Jumia product data, Cleaned and prepared it, analyzed the information, created PivotTables and finally build an interactive dashboard.&lt;/p&gt;

&lt;p&gt;This project also showed me that even a relatively simple dataset can provide useful insights when it is properly when it is properly organized and analyzed.&lt;/p&gt;

&lt;p&gt;This is one of my first steps in building my data analytics portfolio, and I plan to continue improving my skills by working on more projects using Excel, SQL, Python and other data analytics tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  My GitHub project
&lt;/h3&gt;

&lt;p&gt;The complete project, including the dataset, Excel dashboard and project documentation, is available in my GitHub repository. [&lt;a href="https://github.com/gitosh-star/JUMIA_PRODUCTS_PERFOMANCE_DASHBOARD" rel="noopener noreferrer"&gt;https://github.com/gitosh-star/JUMIA_PRODUCTS_PERFOMANCE_DASHBOARD&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>git</category>
      <category>opensource</category>
      <category>database</category>
    </item>
    <item>
      <title>GETTING STARTED WITH EXCEL FOR DATA ANALYTICS: FROM BASICS TO DATA CLEANING</title>
      <dc:creator>David Gitonga</dc:creator>
      <pubDate>Sat, 29 Aug 2026 18:32:41 +0000</pubDate>
      <link>https://dev.to/david_gitonga_2983/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-4b7</link>
      <guid>https://dev.to/david_gitonga_2983/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-4b7</guid>
      <description>&lt;h1&gt;
  
  
  EXCEL OVERVIEW
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;What is Excel? These is a spreadsheet tool for organizing, analyzing, calculating, and visualizing data.
Wiledy used for personal and professional data management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  EXCEL INTERFACE
&lt;/h2&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0pk6de2hddrbizhssmkk.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0pk6de2hddrbizhssmkk.png" alt=" " width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is an Excel workbook that usually subdivided into work sheets&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Ribbon: Toolbar with commands(Home, insert, data..)
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg41wtgm72m9tj92em9op.png" alt=" " width="800" height="55"&gt;
&lt;/li&gt;
&lt;li&gt;Quick Access Toolbar: save, undo, redo.
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnxubdqvvr7n8rf76pcpu.png" alt=" " width="369" height="364"&gt;
&lt;/li&gt;
&lt;li&gt;Formula Bar: displays cell content&lt;/li&gt;
&lt;li&gt;Rows, columns, cells.
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fto9hksd431y2cr2cnl56.jpg" alt=" " width="376" height="668"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Data validation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The restrictions on the type of data user can input into a cell.
(Dropdown lists, Numbers , ranges, date limits, text length)
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  THE DATA CLEANING
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Data cleaning is the process where you prepare raw datasets so they are accurate, consistent, and ready for analysis. This is a very crucial set because one gets to correct small errors , duplicates which may lead to misleading results in the formulas. Clean data ensures reliability and save time when performing deeper analysis.&lt;/li&gt;
&lt;/ul&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fanz9jl3g5mutmj0v2r0c.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fanz9jl3g5mutmj0v2r0c.png" alt=" " width="800" height="470"&gt;&lt;/a&gt; Raw uncleaned data&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmg113cq0fl0uuv5n5ds7.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmg113cq0fl0uuv5n5ds7.png" alt=" " width="800" height="468"&gt;&lt;/a&gt;Cleaned data&lt;/p&gt;

&lt;h2&gt;
  
  
  DATA CLEANING TECHNIQUES
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Removing duplicates: Prevents inflated results in analysis. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mombasa&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mombasa&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Standardizing text this ensures consistency&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NAIROBI&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NairoBi&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;checking dates: corrects inconsistent format and invalid entries, fixing words format: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;strong&gt;PROPER()&lt;/strong&gt; to standardize capitalization in names.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  DATA FORMARTTING &amp;amp; CLEANING
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Number Formatting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;this changes how numbers display without altering their actual value
&lt;strong&gt;Conditional formatting&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;This highlights cells automatically based on trends or criteria&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CONCLUTION
&lt;/h2&gt;

&lt;p&gt;In conclusion data cleaning in excel is more the a technical step, it is the foundation of reliable analysis. This is a effective data cleaning turns Excel from a simple spreadsheet tool into a powerful engine for analytics.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>analytics</category>
      <category>database</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Workflow Flow From Local Folder To GitHub</title>
      <dc:creator>David Gitonga</dc:creator>
      <pubDate>Fri, 21 Aug 2026 19:40:00 +0000</pubDate>
      <link>https://dev.to/david_gitonga_2983/workflow-flow-from-local-folder-to-github-1480</link>
      <guid>https://dev.to/david_gitonga_2983/workflow-flow-from-local-folder-to-github-1480</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;THE GITHUB PROJECT&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Imagine while creating your repository on GitHub,
you remember that you have to include your excel file or any file that is all the way tacked in your folders and you want to use Git. 
How do you go about it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;GIT&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;How does Git work;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It use Linux , where you use SSH (Secure shell) which let you opens an encrypted terminal session to a remote machine in our case GitHub.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  THIS IS THE TYPICAL WORKFLOW FROM START TO FINISH
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Get Git bash first&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Great now open &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we need a local folder in our Git Bash we run the following commands;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;- ssh - to create a remote login
- ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &amp;lt;adress&amp;gt; - with the correct server_address
- &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-al&lt;/span&gt; ~/.shh- check &lt;span class="k"&gt;if &lt;/span&gt;you have added the new sshkey
- &lt;span class="nb"&gt;ls&lt;/span&gt; - which is listing the files and  directories &lt;span class="k"&gt;in &lt;/span&gt;the active directory
- &lt;span class="nb"&gt;cd&lt;/span&gt; - which opens a directory
- &lt;span class="nb"&gt;mkdir&lt;/span&gt; &amp;lt;name&amp;gt; - make a new directory
- &lt;span class="nb"&gt;touch &lt;/span&gt;file.text - to create an empty file
- nano file.text - write a comment or context of the data use &lt;span class="k"&gt;in &lt;/span&gt;place or &lt;span class="nt"&gt;-echo-&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;CREAT REPOSITORY ON GITHUB COPY SSH&lt;span class="o"&gt;}&lt;/span&gt;
- git remote add origin &amp;lt;ssh_key&amp;gt; - &lt;span class="nb"&gt;link &lt;/span&gt;to the remote server
- git commit - commit the &lt;span class="nb"&gt;link&lt;/span&gt;
- git status - check the branch
- git fetch - download a latest change 
- git push - to GitHub

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  CONCLUTION
&lt;/h2&gt;

&lt;p&gt;Git is easy once you understand the commands.&lt;br&gt;
Refresh your GitHub and watch as you have connected. &lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>lux</category>
      <category>ssh</category>
    </item>
    <item>
      <title>Onboarding Session At Lux DevHq</title>
      <dc:creator>David Gitonga</dc:creator>
      <pubDate>Tue, 11 Aug 2026 12:10:02 +0000</pubDate>
      <link>https://dev.to/david_gitonga_2983/onboarding-session-at-lux-devhq-1b3i</link>
      <guid>https://dev.to/david_gitonga_2983/onboarding-session-at-lux-devhq-1b3i</guid>
      <description>&lt;h1&gt;
  
  
  Introduction to lux dev
&lt;/h1&gt;

&lt;p&gt;This are all the things I've learned today about how to write articles it's roles and how to ensure you write a good article&lt;br&gt;
&lt;strong&gt;asterisks for bold&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;dash for italics&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;greater than for quotes &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  line of code
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;SELECT * FROM Cohort9,application;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  writing a block of code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt; &lt;span class="n"&gt;name_&lt;/span&gt;
&lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;three&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;commas&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  photo session
&lt;/h2&gt;

&lt;p&gt;how to upload select from the upload icon, devto converts it to marklaguage&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb45k0rlexe4w4k5v6bz5.webp" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb45k0rlexe4w4k5v6bz5.webp" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  how to add a URL link
&lt;/h2&gt;

&lt;p&gt;This is the link to the luxdev git hub link&lt;br&gt;
link:&lt;a&gt;luxdevHQ&lt;/a&gt;&lt;/p&gt;

</description>
      <category>datascience</category>
    </item>
  </channel>
</rss>
