<?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: Mohammed Swaleh</title>
    <description>The latest articles on DEV Community by Mohammed Swaleh (@maditech).</description>
    <link>https://dev.to/maditech</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%2F4071712%2F1df7d292-c5c6-4d4c-9e9a-90e823cea4e6.png</url>
      <title>DEV Community: Mohammed Swaleh</title>
      <link>https://dev.to/maditech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maditech"/>
    <language>en</language>
    <item>
      <title>SQL for Hospital Data Analysis: Window Functions, Joins, CTEs, and Subqueries</title>
      <dc:creator>Mohammed Swaleh</dc:creator>
      <pubDate>Sat, 17 Oct 2026 17:56:56 +0000</pubDate>
      <link>https://dev.to/maditech/sql-for-hospital-data-analysis-window-functions-joins-ctes-and-subqueries-3b8h</link>
      <guid>https://dev.to/maditech/sql-for-hospital-data-analysis-window-functions-joins-ctes-and-subqueries-3b8h</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;This article explains four core SQL areas using the hospital dataset: &lt;code&gt;doctors&lt;/code&gt;, &lt;code&gt;department&lt;/code&gt;, &lt;code&gt;diagnosis&lt;/code&gt;, &lt;code&gt;wards&lt;/code&gt;, &lt;code&gt;patients&lt;/code&gt;, &lt;code&gt;procedures&lt;/code&gt;, and &lt;code&gt;visits&lt;/code&gt;. The &lt;code&gt;visits&lt;/code&gt; table is the central fact table: each row records one patient visit, including the doctor, department, ward, diagnosis, procedure, admission type, length of stay, bill amount, payment method, and satisfaction score. [file:1]&lt;/p&gt;

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

&lt;p&gt;A window function performs a calculation across a set of related rows—called a &lt;em&gt;window&lt;/em&gt;—without collapsing those rows into one output row. This differs from &lt;code&gt;GROUP BY&lt;/code&gt;, which returns one row per group. Window functions are useful in a hospital setting when you need to retain individual visit details while also showing department totals, rankings, running totals, or comparisons with previous visits. [file:1]&lt;/p&gt;

&lt;h3&gt;
  
  
  How &lt;code&gt;OVER()&lt;/code&gt; works
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;OVER()&lt;/code&gt; defines the window over which the function operates.&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;total_bill_kes&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;hospital_average_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It returns every visit and adds the average bill across all visits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Every row remains visible, but each row has the same hospital-wide average bill. This helps identify visits whose cost is above or below the hospital average.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;PARTITION BY&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;PARTITION BY&lt;/code&gt; divides rows into groups before applying the window function. It is like &lt;code&gt;GROUP BY&lt;/code&gt;, except it does not reduce the number of rows.&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;total_bill_kes&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;department_id&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;department_average_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It calculates the average bill separately for Cardiology, General Medicine, Orthopedics, and Pediatrics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; A Cardiology visit receives the Cardiology average, while an Orthopedics visit receives the Orthopedics average.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ORDER BY&lt;/code&gt; in a window
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ORDER BY&lt;/code&gt; determines the sequence of rows within each partition. It is essential for rankings and running 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;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;visit_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;total_bill_kes&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;department_id&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;visit_date&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;running_department_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It calculates a running total of bills by department, ordered by visit date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; For each department, the first visit shows its own bill, the second shows the sum of the first two bills, and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Window frames
&lt;/h3&gt;

&lt;p&gt;A window frame controls exactly which rows are included in the calculation. The default frame for ordered aggregate functions is usually:&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;RANGE&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can make the frame explicit:&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;visit_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;total_bill_kes&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;department_id&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;visit_date&lt;/span&gt;
        &lt;span class="k"&gt;ROWS&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="mi"&gt;1&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;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;two_visit_moving_average&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; For each visit, it averages the current bill and the immediately preceding bill within the same department.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; This produces a two-visit moving average, useful for identifying short-term changes in departmental billing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ranking functions
&lt;/h3&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;Purpose&lt;/th&gt;
&lt;th&gt;Tie behaviour&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ROW_NUMBER()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Assigns a unique sequential number&lt;/td&gt;
&lt;td&gt;No ties; every row receives a different number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RANK()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ranks rows with gaps after ties&lt;/td&gt;
&lt;td&gt;Tied rows share a rank; the next rank skips&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DENSE_RANK()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ranks rows without gaps&lt;/td&gt;
&lt;td&gt;Tied rows share a rank; the next rank does not skip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NTILE(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Divides rows into &lt;code&gt;n&lt;/code&gt; approximately equal groups&lt;/td&gt;
&lt;td&gt;Useful for quartiles, quintiles, and segments&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;ROW_NUMBER()&lt;/code&gt;
&lt;/h4&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&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;department_id&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;total_bill_kes&lt;/span&gt; &lt;span class="k"&gt;DESC&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;bill_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It numbers visits from highest to lowest bill within each department.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; The most expensive visit in each department receives &lt;code&gt;1&lt;/code&gt;, the next receives &lt;code&gt;2&lt;/code&gt;, and so on. Even if two bills are equal, they receive different row numbers.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;RANK()&lt;/code&gt;
&lt;/h4&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&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;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;department_id&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;total_bill_kes&lt;/span&gt; &lt;span class="k"&gt;DESC&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;bill_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It ranks visits by bill amount within each department, allowing tied ranks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; If two visits tie for the highest bill, both receive rank &lt;code&gt;1&lt;/code&gt;, and the next visit receives rank &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;DENSE_RANK()&lt;/code&gt;
&lt;/h4&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&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;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;department_id&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;total_bill_kes&lt;/span&gt; &lt;span class="k"&gt;DESC&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;dense_bill_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It ranks visits like &lt;code&gt;RANK()&lt;/code&gt; but does not skip ranks after ties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; If two visits tie at rank &lt;code&gt;1&lt;/code&gt;, the next visit receives rank &lt;code&gt;2&lt;/code&gt;, not &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comparison:&lt;/strong&gt; Use &lt;code&gt;ROW_NUMBER()&lt;/code&gt; when you need a unique position, &lt;code&gt;RANK()&lt;/code&gt; when tied values should share a position and gaps are acceptable, and &lt;code&gt;DENSE_RANK()&lt;/code&gt; when tied values should share a position without gaps.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;NTILE()&lt;/code&gt;
&lt;/h4&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&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;total_bill_kes&lt;/span&gt; &lt;span class="k"&gt;DESC&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;bill_quartile&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It divides all visits into four bill-value groups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Quartile &lt;code&gt;1&lt;/code&gt; contains the highest-billing visits, while quartile &lt;code&gt;4&lt;/code&gt; contains the lowest-billing visits. Hospital managers can use this to review the most expensive 25% of visits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Value comparison functions
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;LAG()&lt;/code&gt;
&lt;/h4&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;visit_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;LAG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;patient_id&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;visit_date&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;previous_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; For each patient, it retrieves the bill from the patient’s previous visit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; A patient’s first visit has &lt;code&gt;NULL&lt;/code&gt; for &lt;code&gt;previous_bill&lt;/code&gt;; later visits show the previous amount. This can support follow-up cost analysis.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;LEAD()&lt;/code&gt;
&lt;/h4&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;visit_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;LEAD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;patient_id&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;visit_date&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;next_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; For each patient, it retrieves the bill from the next visit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; The patient’s final visit has &lt;code&gt;NULL&lt;/code&gt; for &lt;code&gt;next_bill&lt;/code&gt;; earlier visits show the following visit’s bill.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;FIRST_VALUE()&lt;/code&gt;
&lt;/h4&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;visit_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;FIRST_VALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;patient_id&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;visit_date&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;first_visit_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It shows the bill from each patient’s earliest visit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Every visit for the same patient displays that patient’s first recorded bill.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;LAST_VALUE()&lt;/code&gt;
&lt;/h4&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;visit_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;LAST_VALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;patient_id&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;visit_date&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;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;last_visit_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It shows the bill from each patient’s latest visit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Every visit for the same patient displays that patient’s final recorded bill. The explicit frame is important because, without it, &lt;code&gt;LAST_VALUE()&lt;/code&gt; may only look at rows up to the current row.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aggregate window functions
&lt;/h3&gt;

&lt;p&gt;Aggregate window functions calculate totals, averages, counts, and extremes while preserving individual rows.&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;total_bill_kes&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;department_id&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;department_total_bill&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;total_bill_kes&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;department_id&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;department_average_bill&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="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;department_id&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;department_visit_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;MIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;department_id&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;department_minimum_bill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;department_id&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;department_maximum_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; For every visit, it displays the department’s total bill, average bill, number of visits, lowest bill, and highest bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Each department’s summary values repeat on every visit from that department, while the original visit-level data remains visible. This is useful for comparing an individual visit against its department’s performance.&lt;/p&gt;

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

&lt;p&gt;A join combines rows from two or more tables based on a related column. In this hospital database, joins are needed because visit details are separated across &lt;code&gt;patients&lt;/code&gt;, &lt;code&gt;doctors&lt;/code&gt;, &lt;code&gt;department&lt;/code&gt;, &lt;code&gt;diagnosis&lt;/code&gt;, &lt;code&gt;wards&lt;/code&gt;, and &lt;code&gt;procedures&lt;/code&gt;. [file:1]&lt;/p&gt;

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

&lt;p&gt;An &lt;code&gt;INNER JOIN&lt;/code&gt; returns only rows with matching values in 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;visit_id&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;patient_name&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;doctor_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_name&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;total_bill_kes&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;patients&lt;/span&gt; &lt;span class="n"&gt;p&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;patient_id&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;patient_id&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;doctors&lt;/span&gt; &lt;span class="n"&gt;d&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;doctor_id&lt;/span&gt; &lt;span class="o"&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;doctor_id&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;department&lt;/span&gt; &lt;span class="n"&gt;dep&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;department_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&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;What it does:&lt;/strong&gt; It returns only visits that have a matching patient, doctor, and department.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Each row shows a visit with the patient’s name, treating doctor, department, and bill. Visits with missing matching records are excluded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Generate a clean operational report of completed visits with full patient, doctor, and department details.&lt;/p&gt;

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

&lt;p&gt;A &lt;code&gt;LEFT JOIN&lt;/code&gt; returns all rows from the left table and matching rows from the right table. If there is no match, columns from the right table are &lt;code&gt;NULL&lt;/code&gt;.&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;patient_id&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;patient_name&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;visit_id&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;visit_date&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;total_bill_kes&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&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="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;patient_id&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;patient_id&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;What it does:&lt;/strong&gt; It returns every patient, including patients with no recorded visit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Patients with visits show their visit details; patients without visits show &lt;code&gt;NULL&lt;/code&gt; in the visit columns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Identify registered patients who have not attended any hospital visit.&lt;/p&gt;

&lt;p&gt;To find only patients without visits:&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;patient_id&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;patient_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&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="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;patient_id&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;patient_id&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;visit_id&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;A &lt;code&gt;RIGHT JOIN&lt;/code&gt; returns all rows from the right table and matching rows from the left table.&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;doctor_id&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;doctor_name&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;visit_id&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;visit_date&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;doctors&lt;/span&gt; &lt;span class="n"&gt;d&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;doctor_id&lt;/span&gt; &lt;span class="o"&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;doctor_id&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;What it does:&lt;/strong&gt; It returns every doctor, including doctors with no visits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Doctors with visits show their visits; doctors without visits show &lt;code&gt;NULL&lt;/code&gt; visit details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Identify doctors who have not handled any recorded patient visit. The same result can usually be written as a &lt;code&gt;LEFT JOIN&lt;/code&gt; by reversing the table order.&lt;/p&gt;

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

&lt;p&gt;A &lt;code&gt;FULL OUTER JOIN&lt;/code&gt; returns all rows from both tables, matching where possible and using &lt;code&gt;NULL&lt;/code&gt; where no match exists.&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;patient_id&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;patient_name&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;visit_id&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;total_bill_kes&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&lt;/span&gt; &lt;span class="n"&gt;p&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;visits&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;patient_id&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;patient_id&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;What it does:&lt;/strong&gt; It returns all patients and all visits, whether or not they match.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Patients without visits and visits without a matching patient both appear, with &lt;code&gt;NULL&lt;/code&gt; on the unmatched side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Data-quality auditing—for example, detecting orphaned visit records or patients missing visit data. Note that PostgreSQL supports &lt;code&gt;FULL OUTER JOIN&lt;/code&gt;; some database systems use slightly different syntax or do not support it directly. [file:1]&lt;/p&gt;

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

&lt;p&gt;A &lt;code&gt;CROSS JOIN&lt;/code&gt; returns every possible combination of rows from the two tables. It does not require an &lt;code&gt;ON&lt;/code&gt; condition.&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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;procedure_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="n"&gt;dep&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;procedures&lt;/span&gt; &lt;span class="n"&gt;pr&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;What it does:&lt;/strong&gt; It pairs every department with every procedure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; If there are 4 departments and 15 procedures, the result contains 60 rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Build a planning matrix, such as reviewing which procedures could potentially be offered in each department. Use it carefully because the output grows quickly.&lt;/p&gt;

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

&lt;p&gt;A self join compares rows within the same table by using two aliases for that table.&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;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doctor_name&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;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doctor_name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;more_experienced_colleague&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doctor_experience_years&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;doctors&lt;/span&gt; &lt;span class="n"&gt;d1&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;doctors&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doctor_experience_years&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doctor_experience_years&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;What it does:&lt;/strong&gt; For each doctor, it finds colleagues with more experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Dr. Faith Chebet, with 8 years of experience, is paired with all three more experienced doctors; Dr. Peter Otieno, with 15 years, has no more experienced colleague and therefore does not appear. [file:1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Compare doctors, patients, or departments against other records in the same table—for example, identifying senior colleagues for mentorship.&lt;/p&gt;

&lt;h3&gt;
  
  
  Join comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Join type&lt;/th&gt;
&lt;th&gt;Rows returned&lt;/th&gt;
&lt;th&gt;Hospital use case&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 rows&lt;/td&gt;
&lt;td&gt;Report visits with complete patient, doctor, and department details&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-table rows plus matches&lt;/td&gt;
&lt;td&gt;Find patients with no visits&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-table rows plus matches&lt;/td&gt;
&lt;td&gt;Find doctors with no visits&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 rows from both tables&lt;/td&gt;
&lt;td&gt;Audit unmatched patients or visits&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 of rows&lt;/td&gt;
&lt;td&gt;Create a department-procedure planning matrix&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;Rows from one table compared with itself&lt;/td&gt;
&lt;td&gt;Compare doctors by experience&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Common Table Expressions
&lt;/h2&gt;

&lt;p&gt;A Common Table Expression, or CTE, is a named temporary result set defined using &lt;code&gt;WITH&lt;/code&gt;. It makes complex queries easier to read, test, and reuse within one statement.&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;cardiology_visits&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;doctor_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;total_bill_kes&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_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&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;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visit_id&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;patient_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;cardiology_visits&lt;/span&gt; &lt;span class="n"&gt;cv&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;patients&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patient_id&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;patient_id&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;What it does:&lt;/strong&gt; The CTE first selects all Cardiology visits, then the main query joins those visits to patient names.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; A list of Cardiology visits with patient names and bill amounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Isolate one department before performing further analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple CTEs
&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;department_summary&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;department_id&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;total_visits&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;total_bill_kes&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;total_revenue&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;patient_satisfaction_score&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;average_satisfaction&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;department_id&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;high_revenue_departments&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;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;total_visits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;total_revenue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;average_satisfaction&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;department_summary&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;total_revenue&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50000&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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_visits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_revenue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;average_satisfaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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;average_satisfaction&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;high_revenue_departments&lt;/span&gt; &lt;span class="n"&gt;h&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;department&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&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;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_revenue&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;&lt;strong&gt;What it does:&lt;/strong&gt; The first CTE summarizes visits and revenue by department. The second CTE filters for departments earning more than KES 50,000. The final query adds department names.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; A list of high-revenue departments, their visit counts, total revenue, and average patient satisfaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Break a large analytical question into readable stages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recursive CTE
&lt;/h3&gt;

&lt;p&gt;A recursive CTE references itself and is useful for hierarchical or sequential data, such as generating a sequence of dates or walking through an organizational 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;visit_sequence&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="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;visit_number&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;visit_number&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;visit_sequence&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;visit_number&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&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;visit_sequence&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;What it does:&lt;/strong&gt; It generates numbers from 1 to 10.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Ten rows numbered &lt;code&gt;1&lt;/code&gt; through &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hospital use case:&lt;/strong&gt; Generate a date series for a dashboard, such as all dates in June 2026, then left join it to daily visit counts so that days with zero visits still appear.&lt;/p&gt;

&lt;h3&gt;
  
  
  CTEs with joins and aggregation
&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;patient_visit_summary&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;patient_id&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;total_visits&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;total_bill_kes&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;total_spent&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;patient_satisfaction_score&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;average_satisfaction&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;patient_id&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;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patient_name&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;county&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_visits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_spent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;average_satisfaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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;average_satisfaction&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patient_visit_summary&lt;/span&gt; &lt;span class="n"&gt;pvs&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;patients&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;pvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patient_id&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;patient_id&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;pvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_spent&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;&lt;strong&gt;What it does:&lt;/strong&gt; It aggregates each patient’s visit count, total spending, and satisfaction score, then joins the result to patient demographic details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; One row per patient who has visited, ordered from the highest total spending to the lowest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Identify high-value or frequent patients for follow-up, loyalty programmes, or service-quality review.&lt;/p&gt;

&lt;h3&gt;
  
  
  CTEs versus subqueries
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;CTE&lt;/th&gt;
&lt;th&gt;Subquery&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Definition&lt;/td&gt;
&lt;td&gt;A named temporary result set introduced with &lt;code&gt;WITH&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;A query embedded inside another query&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Readability&lt;/td&gt;
&lt;td&gt;Usually clearer for multi-step logic&lt;/td&gt;
&lt;td&gt;Can become difficult to read when deeply nested&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reuse&lt;/td&gt;
&lt;td&gt;Can be referenced multiple times within the same query&lt;/td&gt;
&lt;td&gt;Normally written again if needed in several places&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recursion&lt;/td&gt;
&lt;td&gt;Supports recursive CTEs&lt;/td&gt;
&lt;td&gt;Does not naturally support recursion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scope&lt;/td&gt;
&lt;td&gt;Exists only for the duration of the main query&lt;/td&gt;
&lt;td&gt;Exists only within the enclosing query&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best use&lt;/td&gt;
&lt;td&gt;Multi-step analysis, reusable logic, hierarchical data&lt;/td&gt;
&lt;td&gt;Simple filtering, calculated values, or small derived tables&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Example using a subquery instead of a CTE:&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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_visits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_revenue&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;
&lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&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_id&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;total_visits&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;total_bill_kes&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;total_revenue&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;department_id&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces the same department summary as a CTE, but the CTE version is generally easier to maintain when the logic becomes longer.&lt;/p&gt;

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

&lt;p&gt;A subquery is a query placed inside another SQL statement. Subqueries can return a single value, one column, one row, or an entire table-like result.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scalar subquery
&lt;/h3&gt;

&lt;p&gt;A scalar subquery returns exactly 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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&lt;/span&gt; &lt;span class="o"&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;total_bill_kes&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;visits&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;difference_from_average&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It calculates how much each visit’s bill differs from the hospital-wide average bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Positive values indicate above-average bills; negative values indicate below-average bills.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Flag unusually expensive or inexpensive visits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-correlated subquery
&lt;/h3&gt;

&lt;p&gt;A non-correlated subquery can run independently because it does not refer to 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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;total_bill_kes&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;total_bill_kes&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;visits&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;What it does:&lt;/strong&gt; It returns visits with bills above the hospital average.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Only higher-than-average visits appear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Identify costly visits for cost-control review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Correlated subquery
&lt;/h3&gt;

&lt;p&gt;A correlated subquery refers to a column from the outer query, so it is evaluated in relation to each outer 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;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visit_id&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;department_id&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;total_bill_kes&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;total_bill_kes&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;v2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;visits&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&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;department_id&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;What it does:&lt;/strong&gt; For every visit, it compares that visit’s bill with the average bill in the same department.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Only visits costing more than their department’s average are returned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Detect unusually expensive visits relative to the department, rather than the hospital as a whole.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested subqueries
&lt;/h3&gt;

&lt;p&gt;A nested subquery is a subquery 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;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_name&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;WHERE&lt;/span&gt; &lt;span class="n"&gt;patient_id&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;patient_id&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_id&lt;/span&gt; &lt;span class="o"&gt;=&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_id&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;
        &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department_name&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;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt; It first finds the Cardiology department ID, then finds patients who visited that department.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; A list of patients treated in Cardiology.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Answer layered questions, such as “Which patients were treated in the department named Cardiology?”&lt;/p&gt;

&lt;h3&gt;
  
  
  Subqueries in &lt;code&gt;SELECT&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A subquery in &lt;code&gt;SELECT&lt;/code&gt; is commonly scalar and adds a calculated value to every 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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;visits&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;highest_hospital_bill&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;What it does:&lt;/strong&gt; It displays each visit alongside the highest bill in the hospital.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Every row has the same &lt;code&gt;highest_hospital_bill&lt;/code&gt; value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subqueries in &lt;code&gt;FROM&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A subquery in &lt;code&gt;FROM&lt;/code&gt; acts as a derived table and must be given an alias.&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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_visits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_revenue&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;department_id&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;total_visits&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;total_bill_kes&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;total_revenue&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;department_id&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ds&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;department&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&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;What it does:&lt;/strong&gt; It first summarizes visits by department, then joins the summary to department names.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; One row per department showing visit count and total revenue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subqueries in &lt;code&gt;WHERE&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Subqueries in &lt;code&gt;WHERE&lt;/code&gt; filter rows 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;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;patient_name&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;WHERE&lt;/span&gt; &lt;span class="n"&gt;patient_id&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;patient_id&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;total_bill_kes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20000&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;What it does:&lt;/strong&gt; It returns patients who had at least one visit costing more than KES 20,000.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Only patients associated with high-cost visits appear.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;IN&lt;/code&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;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patient_name&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;county&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;span class="k"&gt;WHERE&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;patient_id&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;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patient_id&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;admission_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Inpatient'&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;What it does:&lt;/strong&gt; It returns patients who have had at least one inpatient admission.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; A list of admitted patients.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Identify patients who required hospital admission.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;EXISTS&lt;/code&gt; returns &lt;code&gt;TRUE&lt;/code&gt; if the subquery returns at least one row. It is often efficient because the database can stop as soon as it finds one matching 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;patient_id&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;patient_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&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="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;patient_id&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;patient_id&lt;/span&gt;
      &lt;span class="k"&gt;AND&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;follow_up_required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Yes'&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;What it does:&lt;/strong&gt; It returns patients with at least one visit requiring follow-up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; A list of patients needing follow-up attention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Support follow-up scheduling and patient-outreach workflows.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;ANY&lt;/code&gt; compares a value with at least one 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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;total_bill_kes&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;total_bill_kes&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_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&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;What it does:&lt;/strong&gt; It returns visits whose bill is greater than at least one General Medicine visit bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Visits that exceed the minimum General Medicine bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Compare a department’s costs against another department’s cost range.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;ALL&lt;/code&gt; compares a value with every 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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_bill_kes&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;total_bill_kes&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;total_bill_kes&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_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&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;What it does:&lt;/strong&gt; It returns visits whose bill is greater than every General Medicine visit bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Only visits more expensive than the highest General Medicine bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Identify exceptional high-cost cases relative to a benchmark department.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Combined Example
&lt;/h2&gt;

&lt;p&gt;The following query combines a CTE, window function, join, and subquery to identify each department’s highest-billing visit.&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;ranked_visits&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;visit_id&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;patient_id&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;department_id&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;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&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;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&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;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&lt;/span&gt; &lt;span class="k"&gt;DESC&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;bill_rank&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&lt;/span&gt; &lt;span class="n"&gt;v&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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_name&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;patient_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ranked_visits&lt;/span&gt; &lt;span class="n"&gt;rv&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;department&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department_id&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;patients&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patient_id&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;patient_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bill_rank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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;What it does:&lt;/strong&gt; The CTE ranks visits by bill amount within each department. The final query keeps only the visit ranked &lt;code&gt;1&lt;/code&gt; in each department and adds department and patient names.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; One row per department, showing that department’s most expensive visit and the patient involved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hospital use case:&lt;/strong&gt; Hospital administrators can use this report to review the most expensive case in each department, investigate whether the cost was justified by the diagnosis or procedure, and identify opportunities for cost management.&lt;/p&gt;

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

&lt;p&gt;SQL window functions, joins, CTEs, and subqueries are essential tools for turning raw hospital records into useful operational and clinical insights. Window functions allow analysts to rank visits, calculate running totals, compare each visit with departmental averages, and examine patient visit patterns without losing visit-level detail. Joins bring together information stored across the patients, doctors, department, diagnosis, wards, and procedures tables to create complete reports. CTEs and subqueries make complex analysis easier to structure, especially when calculating departmental revenue, identifying high-cost visits, finding patients who need follow-up, or detecting data-quality issues. Applied together, these SQL concepts support better hospital decision-making in areas such as resource planning, cost control, patient follow-up, service-quality monitoring, and performance evaluation.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>analytics</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>DBeaver SQL Summary Learning Notes</title>
      <dc:creator>Mohammed Swaleh</dc:creator>
      <pubDate>Thu, 15 Oct 2026 06:59:58 +0000</pubDate>
      <link>https://dev.to/maditech/dbeaver-sql-summary-learning-notes-28fa</link>
      <guid>https://dev.to/maditech/dbeaver-sql-summary-learning-notes-28fa</guid>
      <description>&lt;h2&gt;
  
  
  DBeaver &amp;amp; SQL Summary Learning Notes
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;A step-by-step guide using the Hospital Database worked examples&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Learning Roadmap
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Understand DBeaver and the SQL editor
&lt;/li&gt;
&lt;li&gt;Connect to the database and select a schema
&lt;/li&gt;
&lt;li&gt;Understand tables, columns, keys and constraints
&lt;/li&gt;
&lt;li&gt;Create tables and insert records
&lt;/li&gt;
&lt;li&gt;Retrieve data with SELECT
&lt;/li&gt;
&lt;li&gt;Filter rows with WHERE and operators
&lt;/li&gt;
&lt;li&gt;Sort and limit results
&lt;/li&gt;
&lt;li&gt;Summarise data with aggregate functions
&lt;/li&gt;
&lt;li&gt;Group records with GROUP BY and HAVING
&lt;/li&gt;
&lt;li&gt;Join related tables
&lt;/li&gt;
&lt;li&gt;Modify records and table structures
&lt;/li&gt;
&lt;li&gt;Delete data safely and understand table removal
&lt;/li&gt;
&lt;li&gt;Write SQL in the correct order and practise
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. DBeaver and the SQL Editor
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Connect to PostgreSQL database.
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;SQL Editor&lt;/strong&gt; → run queries with &lt;code&gt;Ctrl+Enter&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Inspect &lt;strong&gt;Results grid&lt;/strong&gt; and error panel.
&lt;/li&gt;
&lt;li&gt;Use comments:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="c1"&gt;-- Show all doctors&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;doctors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="cm"&gt;/* This query returns all rows and columns */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Create and Select a Schema
&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;CREATE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;morning&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;search_path&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;morning&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;search_path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Tables, Columns, Keys and Constraints
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common Data Types
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;INT&lt;/code&gt; → whole numbers
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VARCHAR(n)&lt;/code&gt; → text
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DATE&lt;/code&gt; → YYYY-MM-DD
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NUMERIC(10,2)&lt;/code&gt; → decimals
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SERIAL&lt;/code&gt; → auto-increment integer
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Constraints
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PRIMARY KEY&lt;/code&gt;, &lt;code&gt;FOREIGN KEY&lt;/code&gt;, &lt;code&gt;NOT NULL&lt;/code&gt;, &lt;code&gt;UNIQUE&lt;/code&gt;, &lt;code&gt;CHECK&lt;/code&gt;, &lt;code&gt;DEFAULT&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&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;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;doctors&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;doctor_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;doctor_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;doctor_gender&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;doctor_specialty&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;doctor_experience_years&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Insert Records
&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;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;doctors&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doctor_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doctor_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doctor_gender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doctor_specialty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doctor_experience_years&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Dr. Brian Mwangi'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Male'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Cardiologist'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Dr. Sarah Wanjiku'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Female'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'General Physician'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&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;doctors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Retrieve Data with SELECT
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- All columns&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;doctors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Selected columns&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;doctor_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doctor_name&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;doctors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Alias&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;doctor_id&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;doctor_name&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="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Limit rows&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;doctors&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Filtering Rows
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Comparison Operators
&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="o"&gt;*&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;WHERE&lt;/span&gt; &lt;span class="n"&gt;patient_age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&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;patients&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;patient_age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&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;patients&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;patient_age&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Logical Operators
&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="o"&gt;*&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;WHERE&lt;/span&gt; &lt;span class="n"&gt;patient_gender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Male'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;patient_age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;40&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;patients&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;patient_gender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Male'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;patient_age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;40&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;patients&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="n"&gt;patient_gender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Male'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  IN, NOT IN, NULL, DISTINCT
&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="o"&gt;*&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;triage_level&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Green'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'Yellow'&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;visits&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ward_id&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&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;DISTINCT&lt;/span&gt; &lt;span class="n"&gt;insurance_provider&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Sorting and Limiting
&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;visit_date&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;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;visit_date&lt;/span&gt; &lt;span class="k"&gt;DESC&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;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patient_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patient_age&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;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;patient_age&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. Aggregate Functions
&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="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;total_patients&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&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;patient_age&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;average_age&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&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;total_bill_kes&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;total_billed&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;MIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_bill_kes&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;visits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. GROUP BY and HAVING
&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;patient_gender&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;patient_age&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;patients&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;patient_gender&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;doctor_id&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;total_bill_kes&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;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;doctor_id&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;total_bill_kes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. Joins
&lt;/h2&gt;

&lt;h3&gt;
  
  
  INNER JOIN
&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;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visit_id&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;visit_date&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;patient_name&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;doctor_name&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;total_bill_kes&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visits&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;patients&lt;/span&gt; &lt;span class="n"&gt;p&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;patient_id&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;patient_id&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;doctors&lt;/span&gt; &lt;span class="n"&gt;d&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;doctor_id&lt;/span&gt; &lt;span class="o"&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;doctor_id&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;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visit_date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  LEFT JOIN
&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;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patient_id&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;patient_name&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;visit_id&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&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="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;patient_id&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;patient_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  11. Modify Records
&lt;/h2&gt;

&lt;h3&gt;
  
  
  UPDATE
&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;UPDATE&lt;/span&gt; &lt;span class="n"&gt;doctors&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;doctor_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Dr. Peter Ochieng'&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;doctor_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;103&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DELETE
&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;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;triage&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;triage_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;triage&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;risk_level&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  12. Alter Table
&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;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;doctors&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;doctors&lt;/span&gt; &lt;span class="k"&gt;RENAME&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;doctors_email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;triage&lt;/span&gt; &lt;span class="k"&gt;RENAME&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;dim_triage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  13. DELETE vs TRUNCATE vs DROP
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Removes&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DELETE FROM table WHERE…&lt;/td&gt;
&lt;td&gt;Selected rows&lt;/td&gt;
&lt;td&gt;Specific records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE FROM table&lt;/td&gt;
&lt;td&gt;All rows&lt;/td&gt;
&lt;td&gt;Retain structure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TRUNCATE TABLE&lt;/td&gt;
&lt;td&gt;All rows efficiently&lt;/td&gt;
&lt;td&gt;Empty table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DROP TABLE&lt;/td&gt;
&lt;td&gt;Table + structure&lt;/td&gt;
&lt;td&gt;Remove table&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  14. SQL Order
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Writing order:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execution order:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;FROM/JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  15. Practical Patterns
&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;patient_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length_of_stay_days&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;length_of_stay_days&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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;visit_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patient_id&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;payment_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Cash'&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;insurance_provider&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;total_bill_kes&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;total_revenue&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;insurance_provider&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;total_revenue&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  16. Common Mistakes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use exact column names (&lt;code&gt;patient_age&lt;/code&gt;, not &lt;code&gt;patients_age&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Use single quotes for text/date values.
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;IS NULL&lt;/code&gt;, not &lt;code&gt;= NULL&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Always add &lt;code&gt;WHERE&lt;/code&gt; in &lt;code&gt;UPDATE&lt;/code&gt;/&lt;code&gt;DELETE&lt;/code&gt; unless affecting all rows.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  17. Suggested Practice Sequence
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Display all patients.
&lt;/li&gt;
&lt;li&gt;Find patients aged ≤ 30.
&lt;/li&gt;
&lt;li&gt;List visits between 1–10 June 2026.
&lt;/li&gt;
&lt;li&gt;Count visits and average bill.
&lt;/li&gt;
&lt;li&gt;Calculate total billed by admission_type.
&lt;/li&gt;
&lt;li&gt;Find patients with &amp;gt;1 visit.
&lt;/li&gt;
&lt;li&gt;Join visits with patients and doctors.
&lt;/li&gt;
&lt;li&gt;Alter a table (add/rename/drop column).
&lt;/li&gt;
&lt;li&gt;Compare DELETE, TRUNCATE, DROP.
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  18. Quick Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need to…&lt;/th&gt;
&lt;th&gt;SQL keyword&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read data&lt;/td&gt;
&lt;td&gt;SELECT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose source table&lt;/td&gt;
&lt;td&gt;FROM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filter rows&lt;/td&gt;
&lt;td&gt;WHERE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remove duplicates&lt;/td&gt;
&lt;td&gt;DISTINCT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sort results&lt;/td&gt;
&lt;td&gt;ORDER BY&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Limit rows&lt;/td&gt;
&lt;td&gt;LIMIT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aggregate&lt;/td&gt;
&lt;td&gt;COUNT, SUM, AVG, MIN, MAX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Group&lt;/td&gt;
&lt;td&gt;GROUP BY&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filter groups&lt;/td&gt;
&lt;td&gt;HAVING&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Combine tables&lt;/td&gt;
&lt;td&gt;JOIN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add rows&lt;/td&gt;
&lt;td&gt;INSERT INTO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change rows&lt;/td&gt;
&lt;td&gt;UPDATE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remove rows&lt;/td&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change structure&lt;/td&gt;
&lt;td&gt;ALTER TABLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empty table&lt;/td&gt;
&lt;td&gt;TRUNCATE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remove table&lt;/td&gt;
&lt;td&gt;DROP TABLE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




</description>
      <category>database</category>
      <category>postgres</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>From Raw Data to Business Decisions: JCars Logistics Power BI Project</title>
      <dc:creator>Mohammed Swaleh</dc:creator>
      <pubDate>Fri, 02 Oct 2026 08:00:20 +0000</pubDate>
      <link>https://dev.to/maditech/from-raw-data-to-business-decisions-jcars-logistics-power-bi-project-4i13</link>
      <guid>https://dev.to/maditech/from-raw-data-to-business-decisions-jcars-logistics-power-bi-project-4i13</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;JCars Logistics, a leading vehicle importer and distributor in Kenya, wanted to transform its raw operational data into actionable insights. The dataset contained thousands of records on sales, customers, vehicles, branches, payments, deliveries, logistics costs, returns, and cancellations.  &lt;/p&gt;

&lt;p&gt;The challenge: build a &lt;strong&gt;Power BI solution&lt;/strong&gt; that moves from messy raw data to a clean, interactive dashboard that helps management answer critical business questions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Data Preparation
&lt;/h2&gt;

&lt;p&gt;The raw dataset was full of issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inconsistent date formats (&lt;code&gt;Aug 29, 2025&lt;/code&gt;, &lt;code&gt;2026-13-04&lt;/code&gt;, &lt;code&gt;not sure&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Mixed currencies (KES, USD, EUR, ZAR).
&lt;/li&gt;
&lt;li&gt;Spelling variations (&lt;code&gt;Toyta&lt;/code&gt;, &lt;code&gt;totoya&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Missing values (customer age, vehicle year).
&lt;/li&gt;
&lt;li&gt;Suspicious entries (negative revenue, units sold = -1)&lt;/li&gt;
&lt;li&gt;Duplicate or inconsistent IDs (ORD1020 appears twice).&lt;/li&gt;
&lt;li&gt;Mixed numeric formats (0.08M vs 80,000).&lt;/li&gt;
&lt;li&gt;Text in numeric fields (Discount “ten percent”).&lt;/li&gt;
&lt;li&gt;Outliers (Customer Age = 121).&lt;/li&gt;
&lt;li&gt;Invalid dates (31/02/2026).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using &lt;strong&gt;Power Query&lt;/strong&gt;, the task involved the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standardized date formats.
&lt;/li&gt;
&lt;li&gt;Converted all monetary values into &lt;strong&gt;Kenya Shillings (KES)&lt;/strong&gt; using Central Bank exchange rates.
&lt;/li&gt;
&lt;li&gt;Corrected spelling and standardized categories.
&lt;/li&gt;
&lt;li&gt;Flagged unusual records instead of deleting them.
&lt;/li&gt;
&lt;li&gt;Created a clean, analysis‑ready model.&lt;/li&gt;
&lt;li&gt;Normalize text (uppercase/lowercase, spelling corrections).&lt;/li&gt;
&lt;li&gt;Convert numeric fields to proper data types.&lt;/li&gt;
&lt;li&gt;Replace or flag missing values.&lt;/li&gt;
&lt;li&gt;Standardize categorical values (Payment Status, Delivery Status).&lt;/li&gt;
&lt;li&gt;Create calculated fields if needed (e.g., Gross Profit = Revenue – Cost – Logistics).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Data Modelling
&lt;/h2&gt;

&lt;p&gt;I reorganized the flat file into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fact Table:&lt;/strong&gt; Orders (sales, costs, revenue, logistics).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dimension Tables:&lt;/strong&gt; Customers, Vehicles, Branches, Sales Reps, Dates.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Relationships were defined using &lt;code&gt;Order ID&lt;/code&gt;, &lt;code&gt;Customer ID&lt;/code&gt;, and &lt;code&gt;Branch ID&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  DAX Measures
&lt;/h2&gt;

&lt;p&gt;Key measures included:&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 = SUM(fact_orders[RevenueRecorded])

Gross Profit =
SUMX(
    fact_orders,
    fact_orders[RevenueRecorded] - fact_orders[UnitCost] - fact_orders[LogisticsCost]
)

Gross Profit Margin = DIVIDE([Gross Profit], [Total Revenue], 0)

Return Rate =
DIVIDE(
    CALCULATE(COUNTROWS(fact_orders), fact_orders[Returned] = "Yes"),
    COUNTROWS(fact_orders),
    0
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These measures allowed management to track profitability, efficiency, and customer behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Executive Dashboard
&lt;/h2&gt;

&lt;p&gt;The one‑page dashboard highlighted:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;KPIs&lt;/strong&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Revenue (&lt;code&gt;KES 1.44B&lt;/code&gt;), &amp;gt; Units Sold (&lt;code&gt;458&lt;/code&gt;), &amp;gt; Orders (&lt;code&gt;276&lt;/code&gt;), &amp;gt; Avg Order Value (&lt;code&gt;KES 5.6M)&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Trends&lt;/strong&gt;: Monthly revenue fluctuations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Breakdowns&lt;/strong&gt;: Revenue by Region, Vehicle Type, Sales Rep, Lead Source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alerts&lt;/strong&gt;: High cancellations, unusual logistics costs.&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%2Fl9uo0vgw2whpfcn24jny.jpg" 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%2Fl9uo0vgw2whpfcn24jny.jpg" alt="order dashboard" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Detailed Reports
&lt;/h2&gt;

&lt;p&gt;Additional pages allowed deeper investigation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Regional Performance&lt;/strong&gt;: Rift Valley leads with 25.3% of revenue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vehicle Performance&lt;/strong&gt;: SUVs dominate with 57.8% of revenue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sales Rep Analysis&lt;/strong&gt;: Faith Achieng contributes 14.5% of revenue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lead Source Analysis&lt;/strong&gt;: Instagram and Facebook drive the highest sales.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Returns &amp;amp; Cancellations&lt;/strong&gt;: Certain models (e.g., Toyota LC200, Subaru XV) show higher return rates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Insights
&lt;/h2&gt;

&lt;p&gt;SUVs are the backbone of JCars revenue, but pickups and sedans provide stronger margins.&lt;/p&gt;

&lt;p&gt;Rift Valley dominates regional sales, while Nairobi suffers from cancellations.&lt;/p&gt;

&lt;p&gt;Digital channels outperform traditional lead sources — Instagram and Facebook are critical.&lt;/p&gt;

&lt;p&gt;Top reps drive disproportionate revenue — Faith Achieng alone contributes 14.5%.&lt;/p&gt;

&lt;p&gt;Future‑dated and cancelled orders distort reporting, requiring stricter validation.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Investigate Nairobi operations to reduce cancellations and improve delivery reliability.&lt;/li&gt;
&lt;li&gt;Expand SUV inventory but balance with pickups and sedans for profitability.&lt;/li&gt;
&lt;li&gt;Invest further in digital marketing, especially Instagram and Facebook.&lt;/li&gt;
&lt;li&gt;Replicate top rep practices through training and mentorship.&lt;/li&gt;
&lt;li&gt;Strengthen data governance to prevent future‑dated and erroneous entries.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;This project demonstrates how Power BI can transform raw, inconsistent data into a decision‑support tool. By cleaning, modelling, and visualizing the dataset, JCars Logistics now has a clear view of performance drivers, risks, and opportunities.&lt;/p&gt;

&lt;p&gt;The journey from raw CSV to polished dashboard highlights the importance of data quality, modelling discipline, and actionable insights in business intelligence.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>powerfuldevs</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Building Effective Power BI Data Models: Schemas, Relationships, and Joins Explained</title>
      <dc:creator>Mohammed Swaleh</dc:creator>
      <pubDate>Sun, 27 Sep 2026 19:40:53 +0000</pubDate>
      <link>https://dev.to/maditech/building-effective-power-bi-data-models-schemas-relationships-and-joins-explained-40p1</link>
      <guid>https://dev.to/maditech/building-effective-power-bi-data-models-schemas-relationships-and-joins-explained-40p1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A well-designed data model is the foundation of every successful Power BI solution. It determines how fast your reports load, how simple your DAX formulas are, and how easily your solution can scale as your business grows. This article walks through the core concepts of data modelling in Power BI—covering schema design, fact and dimension tables, relationships, filter direction, and joins in Power Query—so you can build models that are performant, maintainable, and intuitive for report authors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Data Modelling in Power BI&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What is Data Modelling and Why Does it Matter?&lt;/strong&gt;&lt;br&gt;
Data modelling in Power BI is the process of structuring your data into tables, defining how those tables relate to one another, and organising them in a way that supports efficient querying, accurate calculations, and intuitive report building.&lt;/p&gt;

&lt;p&gt;A well-designed data model is critical for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reporting and analytics&lt;/strong&gt;: Clean, logical structures make it easier for users to drag and drop fields without confusion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DAX calculations&lt;/strong&gt;: Simpler models lead to simpler, more reliable measures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Efficient schemas reduce the amount of data Power BI needs to scan and filter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Good models grow gracefully as data volumes and business requirements expand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Clear structures are easier to document, troubleshoot, and hand over to other developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Modelling Approaches: Flat Table, Star Schema, and Snowflake Schema&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flat Table&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Definition&lt;/strong&gt;: A flat table is a single table where all data—facts and descriptive attributes—resides in one large table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One table with many columns. Columns for facts (sales amount, quantity) and attributes (customer name, product category)&lt;/li&gt;
&lt;li&gt;No relationships; everything is in one place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to understand for beginners.&lt;/li&gt;
&lt;li&gt;No need to manage relationships.&lt;/li&gt;
&lt;li&gt;Quick to build for very small datasets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High data redundancy (e.g., customer name repeated on every sales row).&lt;/li&gt;
&lt;li&gt;Larger file size and slower refresh.&lt;/li&gt;
&lt;li&gt;Harder to maintain as business rules change.&lt;/li&gt;
&lt;li&gt;DAX can become complex when handling repeated attributes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When appropriate:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very small datasets or one-off analyses.&lt;/li&gt;
&lt;li&gt;Prototyping or quick proofs of concept.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implications for Power BI:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Poor performance at scale due to redundancy.&lt;/li&gt;
&lt;li&gt;Increased model size and memory usage.&lt;/li&gt;
&lt;li&gt;Difficult to extend or refactor later.&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%2Fl7wh2own2a5dsa19exgw.jpg" 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%2Fl7wh2own2a5dsa19exgw.jpg" alt="flat table" width="800" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For instance, all descriptive attributes like PatientsName, PatientsGender, PatientsAge are repeated on every row&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Normalization&lt;/strong&gt; - &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;breaking down tables into smaller tables to reduce redundancies&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Star Schema
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt;: A star schema consists of a central fact table surrounded by dimension tables, each connected via one-to-many relationships. A Central fact table connected to multiple dimension tables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One fact table in the centre, surrounded by Multiple dimension tables radiating out like a star.&lt;/li&gt;
&lt;li&gt;Each dimension connects directly to the fact table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimised for Power BI's tools, clear relationships, efficient queries.&lt;/li&gt;
&lt;li&gt;Minimal DAX complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires upfront modelling effort.&lt;/li&gt;
&lt;li&gt;Slightly more tables to manage than a flat table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When appropriate:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Most business intelligence and reporting scenarios.&lt;/li&gt;
&lt;li&gt;When performance and usability are priorities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implications for Power BI:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Best-practice schema for Power BI.&lt;/li&gt;
&lt;li&gt;Excellent query performance and DAX simplicity.&lt;/li&gt;
&lt;li&gt;Scales well with large fact tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Illustration:&lt;/strong&gt;&lt;br&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%2Feqnjikryuyzyhrrp2qi7.jpg" 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%2Feqnjikryuyzyhrrp2qi7.jpg" alt="star schema" width="623" height="442"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Snowflake Schema
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt;: A snowflake schema is a variation of the star schema where dimension tables are further normalised into sub-dimensions, creating a "snowflake" shape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Central fact table.eg  Hospital_visits_fact_table&lt;/li&gt;
&lt;li&gt;Dimension tables that are normalised into multiple related tables.&lt;/li&gt;
&lt;li&gt;Example: DimPatients → DimPatientsCounty → DimPatientsSubcounty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduced data redundancy in dimensions.&lt;/li&gt;
&lt;li&gt;More "database-normalised" design.&lt;/li&gt;
&lt;li&gt;Useful when dimensions are very large and highly structured.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More complex model with longer relationship chains.&lt;/li&gt;
&lt;li&gt;Potentially slower filter propagation.&lt;/li&gt;
&lt;li&gt;Harder for report authors to understand and to navigate&lt;/li&gt;
&lt;li&gt;More tables in the Data pane, which can confuse users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When appropriate:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very large, highly normalised data warehouses.&lt;/li&gt;
&lt;li&gt;When dimension tables are extremely wide and benefit from normalisation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implications for Power BI:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Often unnecessary complexity for typical BI projects.&lt;/li&gt;
&lt;li&gt;Can degrade performance due to longer filter paths.&lt;/li&gt;
&lt;li&gt;Microsoft generally recommends star schema over snowflake for Power BI.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Fact Tables and Dimension Tables
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fact Table
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A fact table&lt;/strong&gt; stores measurable, numeric events—typically transactions or occurrences that you want to analyse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical contents:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Numeric measures: SalesAmount, Quantity, Cost, Profit.&lt;/li&gt;
&lt;li&gt;Foreign keys to dimension tables: CustomerID, ProductID, DateKey.&lt;/li&gt;
&lt;li&gt;Very little descriptive text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Grain (granularity):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The grain defines the level of detail in the fact table.&lt;/li&gt;
&lt;li&gt;Example: One row per sales transaction line item.&lt;/li&gt;
&lt;li&gt;Grain determines what you can aggregate and how you slice data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FactSales: One row per sales order line.&lt;/li&gt;
&lt;li&gt;FactOrders: One row per order or order line.&lt;/li&gt;
&lt;li&gt;FactTransactions: One row per financial transaction.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;What is a Dimension Table?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A dimension table&lt;/strong&gt; stores descriptive attributes used to slice, filter, and group facts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical contents:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primary key: CustomerID, ProductID, DateKey.&lt;/li&gt;
&lt;li&gt;Descriptive columns: CustomerName, ProductName, Category, Country, Month.&lt;/li&gt;
&lt;li&gt;Hierarchies: Year → Quarter → Month → Day; Category → Subcategory → Product.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DimCustomer: CustomerID, CustomerName, Segment, Region.&lt;/li&gt;
&lt;li&gt;DimProduct: ProductID, ProductName, Category, Brand.&lt;/li&gt;
&lt;li&gt;DimDate: DateKey, Date, Day, Month, Quarter, Year.&lt;/li&gt;
&lt;li&gt;DimLocation: LocationID, City, State, Country.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Relationships in Power BI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is a Relationship?&lt;/strong&gt;&lt;br&gt;
A relationship in Power BI defines how two tables are connected based on matching column values. Relationships enable Power BI to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filter data across tables.&lt;/li&gt;
&lt;li&gt;Combine fields from different tables in visuals.&lt;/li&gt;
&lt;li&gt;Calculate measures correctly using DAX.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without relationships, Power BI cannot correctly join data from multiple tables, leading to incorrect totals and broken visuals.&lt;/p&gt;




&lt;h2&gt;
  
  
  Relationship Cardinalities
&lt;/h2&gt;

&lt;p&gt;Power BI supports three main cardinality types:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. One-to-Many (1:*)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One row in the "one" table matches many rows in the "many" table.&lt;/li&gt;
&lt;li&gt;The "one" side must have unique values (primary key).&lt;/li&gt;
&lt;li&gt;The "many" side can have duplicates (foreign key).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;DimProcedure&lt;a href="https://dev.tounique"&gt;ProcedureID&lt;/a&gt; → FactVisit&lt;a href="https://dev.toduplicates"&gt;VisitID&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;One procedure can have many visits; each procedure belongs to one patient visit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Most common relationship in BI models.&lt;/li&gt;
&lt;li&gt;Between dimension tables and fact tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When not to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When both sides have duplicates without a clear "one" side (consider bridge tables or many-to-many).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Illustration:&lt;/strong&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnmh05s4l47299bkbxswd.jpg" 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%2Fnmh05s4l47299bkbxswd.jpg" alt="one to many relationship" width="623" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. One-to-One (1:1)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each row in Table A matches exactly one row in Table B.&lt;/li&gt;
&lt;li&gt;Both sides must have unique values.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;DimEmployee and DimEmployeeDetails, where each employee has exactly one detail record.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Splitting wide tables for manageability.&lt;/li&gt;
&lt;li&gt;Integrating data from different sources with a perfect 1:1 match.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When not to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If there's any possibility of duplicates on either side (use 1:* instead).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Illustration:&lt;/strong&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnfqn64u3r1jb5nsql25e.jpg" 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%2Fnfqn64u3r1jb5nsql25e.jpg" alt="one to one relationship" width="800" height="398"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;em&gt;(Each employee has exactly one detail record.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Many-to-Many (:)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both sides can have duplicate values.&lt;/li&gt;
&lt;li&gt;Power BI creates a virtual bridge to resolve the relationship.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Students and Courses: a student can take many courses; a course can have many students.&lt;/li&gt;
&lt;li&gt;In Power BI, often implemented via a bridge table (e.g., FactEnrolment) to maintain clarity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;True many-to-many business scenarios.&lt;/li&gt;
&lt;li&gt;When no natural "one" side exists.&lt;/li&gt;
&lt;li&gt;When not to use:&lt;/li&gt;
&lt;li&gt;If you can introduce a bridge or fact table to convert to 1:* relationships (preferred for clarity and performance).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Illustration&lt;/strong&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzobnyvhvamhx5161gqpz.jpg" 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%2Fzobnyvhvamhx5161gqpz.jpg" alt="many to many relationship" width="800" height="321"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Multiple students per course; multiple courses per student.)&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Key Relationship Concepts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Primary Keys and Foreign Keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primary Key&lt;/strong&gt;: A column (or set of columns) with unique values that identify each row in a table. Example: CustomerID in DimCustomer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Foreign Key&lt;/strong&gt;: A column in another table that references a primary key. primary key referenced in another table, not unique. Example: CustomerID in FactSales.&lt;/p&gt;

&lt;p&gt;In a 1:* relationship:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The "one" side holds the primary key (unique).&lt;/li&gt;
&lt;li&gt;The "many" side holds the foreign key (duplicates allowed).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Unique Values and Referential Integrity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unique values&lt;/strong&gt; on the "one" side ensure each dimension row is distinct.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referential integrity&lt;/strong&gt; means every foreign key in the fact table matches a valid primary key in the dimension. Violations can cause missing or incorrect data in reports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Active and Inactive Relationships&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Active relationship&lt;/strong&gt;: The default relationship used for filter propagation and DAX calculations. Only one active relationship per table pair for a given column path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inactive relationship&lt;/strong&gt;: Exists but is not used unless explicitly activated in DAX using USERELATIONSHIP. Useful for role-playing dimensions (e.g., OrderDate vs ShipDate both linking to DimDate).&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Filter Direction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How Filters Propagate&lt;/strong&gt;&lt;br&gt;
In Power BI, when a user selects a value in a visual (e.g., a product name), filters propagate through relationships to related tables, affecting which rows are included in calculations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-Direction Filtering
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt;: Filters flow in one direction only—typically from the "one" side to the "many" side in a 1:* relationship.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Selecting "Product A" in DimProduct filters FactSales to show only sales of Product A.&lt;/li&gt;
&lt;li&gt;Filters do not flow back from FactSales to DimProduct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it's preferred:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Predictable behaviour.&lt;/li&gt;
&lt;li&gt;Avoids ambiguous filter paths.&lt;/li&gt;
&lt;li&gt;Better performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bidirectional (Both) Filtering
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt;: Filters flow in both directions between related tables.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;With bidirectional filtering between DimProduct and FactSales:&lt;/li&gt;
&lt;li&gt;Selecting a product filters sales (as usual).&lt;/li&gt;
&lt;li&gt;Selecting a sales record could also filter the product table (less common in practice).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use carefully:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex models with multiple paths between tables.&lt;/li&gt;
&lt;li&gt;Scenarios requiring filters to flow "up" from facts to dimensions (rare).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Potential problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ambiguous filter paths: Power BI may not know which path to use, leading to errors or unexpected results.&lt;/li&gt;
&lt;li&gt;Performance impact: Extra filter propagation can slow down queries.&lt;/li&gt;
&lt;li&gt;Model complexity: Harder to understand and maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use single-direction filtering by default.&lt;/li&gt;
&lt;li&gt;Enable bidirectional filtering only when clearly needed and tested.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Joins in Power Query
&lt;/h2&gt;

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

&lt;p&gt;Combines two tables based on matching columns.&lt;/p&gt;

&lt;h4&gt;
  
  
  Left Outer Join
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Keeps all rows from left + matches from right.
&lt;/li&gt;
&lt;li&gt;Unmatched right rows → null.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Left Outer Join Example&lt;/strong&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyoe7ipc1t7jzifvwfzhn.jpg" 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%2Fyoe7ipc1t7jzifvwfzhn.jpg" alt="left outer join" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Right Outer Join
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Keeps all rows from right + matches from left.
&lt;/li&gt;
&lt;li&gt;Unmatched left rows → null.&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%2Faei5rmbn9s4pqp9imxde.jpg" 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%2Faei5rmbn9s4pqp9imxde.jpg" alt="right outer join" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Full Outer Join
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Keeps all rows from both tables.
&lt;/li&gt;
&lt;li&gt;Unmatched rows → nulls.&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%2Fk9efyfbfu7oyf1tp2iym.jpg" 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%2Fk9efyfbfu7oyf1tp2iym.jpg" alt="full outer join" width="799" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Inner Join
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Keeps only matching rows from both tables.&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%2Footmnul1by79oz1av3wg.jpg" 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%2Footmnul1by79oz1av3wg.jpg" alt="inner join" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Left Anti Join
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Keeps rows from left with no match in right.&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%2F1sey0ebbhacdqom0bypi.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%2F1sey0ebbhacdqom0bypi.png" alt="left anti-join" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Right Anti Join
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Keeps rows from right with no match in left.&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%2Fzjgnc1ypxbmc3unt8hh7.jpg" 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%2Fzjgnc1ypxbmc3unt8hh7.jpg" alt="right anti-join" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Power Query Joins vs Power BI Relationships
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Power Query Merge&lt;/th&gt;
&lt;th&gt;Power BI Relationship&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Combines Data?&lt;/td&gt;
&lt;td&gt;Yes, physically merges columns.&lt;/td&gt;
&lt;td&gt;No, logical link only.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stage&lt;/td&gt;
&lt;td&gt;During ETL (Power Query).&lt;/td&gt;
&lt;td&gt;After load, in model layer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use When&lt;/td&gt;
&lt;td&gt;Need single denormalised table.&lt;/td&gt;
&lt;td&gt;Building relational BI models.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Impact&lt;/td&gt;
&lt;td&gt;Wide, redundant tables.&lt;/td&gt;
&lt;td&gt;Compact, reusable dimensions.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Keep fact and dimension tables separate for clarity, performance, and scalability.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Recommended Power BI Model Design
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Preferred Schema: Star Schema
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimised for Power BI engine.
&lt;/li&gt;
&lt;li&gt;Simple DAX and predictable filters.
&lt;/li&gt;
&lt;li&gt;Clear separation of facts and dimensions.
&lt;/li&gt;
&lt;li&gt;Scalable and maintainable.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Relationship Design:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cardinality: One-to-many (1:*).
&lt;/li&gt;
&lt;li&gt;Filter Direction: Single-direction.
&lt;/li&gt;
&lt;li&gt;Active Relationships: Standard reporting.
&lt;/li&gt;
&lt;li&gt;Inactive Relationships: Role-playing dimensions (activated in DAX).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deviations:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Snowflake schema only for very large, normalised dimensions.
&lt;/li&gt;
&lt;li&gt;Bidirectional filtering only when necessary.
&lt;/li&gt;
&lt;li&gt;Flat table only for small prototypes.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Power BI’s strength lies in well-structured relational models. By adopting a star schema, using one-to-many single-direction relationships, and reserving Power Query merges for specific needs, you create models that are fast, clear, and easy to maintain. Understanding schemas, relationships, filter direction, and joins lets you design solutions that scale and give users accurate, insightful reports.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>learning</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Building an Interactive Excel Dashboard for E-commerce Product Analysis: A Case Study of Jumia Products</title>
      <dc:creator>Mohammed Swaleh</dc:creator>
      <pubDate>Mon, 07 Sep 2026 08:35:23 +0000</pubDate>
      <link>https://dev.to/maditech/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-case-study-of-jumia-15d2</link>
      <guid>https://dev.to/maditech/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-case-study-of-jumia-15d2</guid>
      <description>&lt;h2&gt;
  
  
  Project Introduction and Objective
&lt;/h2&gt;

&lt;p&gt;E-commerce platforms thrive on data. Sellers and marketplaces like Jumia need to understand how pricing, discounts, and customer feedback influence product performance. This project set out to build an interactive Excel dashboard that transforms raw Jumia product data into actionable insights.&lt;/p&gt;

&lt;p&gt;The goal was not just to create charts, but to audit, clean, analyze, and visualize the data in a way that supports evidence-based recommendations for sellers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dataset and Business Questions
&lt;/h2&gt;

&lt;p&gt;The dataset contained product names, current and old prices, advertised discounts, customer reviews, and ratings. Reviews were used as a proxy for engagement, since sales volumes were not available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key business questions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do larger discounts attract more reviews?
&lt;/li&gt;
&lt;li&gt;Do highly rated products show stronger engagement?
&lt;/li&gt;
&lt;li&gt;Is there a relationship between price and rating?
&lt;/li&gt;
&lt;li&gt;Which products perform best, and which need pricing or marketing adjustments?
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Initial Data-Quality Audit
&lt;/h2&gt;

&lt;p&gt;Before cleaning, the dataset revealed several issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Misspelled headers (e.g., &lt;code&gt;Ratingd&lt;/code&gt; instead of &lt;code&gt;Rating&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Negative review counts
&lt;/li&gt;
&lt;li&gt;Blank values in reviews and ratings
&lt;/li&gt;
&lt;li&gt;Prices expressed as ranges
&lt;/li&gt;
&lt;li&gt;Duplicate product rows
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These anomalies were documented in a &lt;strong&gt;Data Dictionary worksheet&lt;/strong&gt; to ensure transparency.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cleaning and Preparation Decisions
&lt;/h2&gt;

&lt;p&gt;Data cleaning followed clear, traceable rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prices:&lt;/strong&gt; stripped of “KSh” and commas, converted to currency (KES).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discounts:&lt;/strong&gt; converted to decimals.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reviews:&lt;/strong&gt; negative signs treated as scraping artifacts, converted to absolute values.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ratings:&lt;/strong&gt; standardized to decimals, blanks left as missing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price ranges:&lt;/strong&gt; replaced with midpoints, while preserving original text for auditability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicates:&lt;/strong&gt; removed only when all fields matched.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  PivotTable and Analysis Workflow
&lt;/h2&gt;

&lt;p&gt;PivotTables powered the analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rating Mix&lt;/strong&gt; → distribution of Poor, Average, Excellent products
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discount Mix&lt;/strong&gt; → proportion of Low, Medium, High discounts
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price vs Rating&lt;/strong&gt; → average rating by price category
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engagement by Discount&lt;/strong&gt; → reviews by discount category
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Top Products&lt;/strong&gt; → ranked by rating, reviews, and discount
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scatter plots with trendlines and correlation coefficients tested relationships between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discounts vs Reviews
&lt;/li&gt;
&lt;li&gt;Ratings vs Reviews
&lt;/li&gt;
&lt;li&gt;Price vs Rating
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dashboard Design and Slicer Connections
&lt;/h2&gt;

&lt;p&gt;The dashboard was designed for &lt;strong&gt;single-screen readability&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KPIs row: total products, average price, average discount, average rating, total reviews
&lt;/li&gt;
&lt;li&gt;Ranked tables: top products by rating, reviews, and discount
&lt;/li&gt;
&lt;li&gt;Scatter plots: discount vs reviews, rating vs reviews, price vs rating
&lt;/li&gt;
&lt;li&gt;Mix charts: rating and discount distributions
&lt;/li&gt;
&lt;li&gt;Slicers: interactive filters for rating, discount, and price categories
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consistent formatting ensured clarity:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KES for prices
&lt;/li&gt;
&lt;li&gt;Decimals for discounts and ratings
&lt;/li&gt;
&lt;li&gt;Thousands separators for reviews
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Findings
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Price vs Rating
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Products priced between &lt;strong&gt;KSh 1600–1999&lt;/strong&gt; show the highest average rating (0.87).
&lt;/li&gt;
&lt;li&gt;Lower-priced items (KSh 400–799) also perform well (0.83).
&lt;/li&gt;
&lt;li&gt;Mid-range prices dip slightly, showing weaker ratings.
➡️ Both affordable and moderately premium products attract better ratings.&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%2Fibsmhsok6r03qhqj1s2n.jpg" 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%2Fibsmhsok6r03qhqj1s2n.jpg" alt="Price Versus Ratings" width="595" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Engagement by Discount
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Engagement peaks in the &lt;strong&gt;0.2–0.3 discount band (~18 reviews)&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Very high discounts (&amp;gt;0.5) show lower engagement (~7 reviews).
➡️ Moderate discounts are the sweet spot for driving customer interaction.&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%2Fwv40cicwbuoa6gcgwr3e.jpg" 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%2Fwv40cicwbuoa6gcgwr3e.jpg" alt="Engagement Versus Discount" width="644" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Top Products by Rating
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Near-perfect ratings (0.96):

&lt;ul&gt;
&lt;li&gt;LASA Folding Table Serving Stand
&lt;/li&gt;
&lt;li&gt;40cm Gold DIY Acrylic Wall Sticker Clock
&lt;/li&gt;
&lt;li&gt;Portable Home Small Air Humidifier
&lt;/li&gt;
&lt;/ul&gt;
&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%2Fwg9791mkl6ptyc6aefa9.jpg" 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%2Fwg9791mkl6ptyc6aefa9.jpg" alt="Top product by Rating" width="550" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Top Products by Reviews
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;120W Cordless Vacuum Cleaner&lt;/strong&gt; leads with 69 reviews but has a low rating (0.56).
&lt;/li&gt;
&lt;li&gt;Other high-engagement products:

&lt;ul&gt;
&lt;li&gt;137 Pieces Cake Decorating Tool Set (55 reviews)
&lt;/li&gt;
&lt;li&gt;Electronic Digital Vernier Caliper (49 reviews)
&lt;/li&gt;
&lt;li&gt;3D Waterproof EVA Shower Curtain (44 reviews)
➡️ High engagement does not always align with high ratings.&lt;/li&gt;
&lt;/ul&gt;
&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%2F6dgj5eja0f4oyin9yrqo.jpg" 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%2F6dgj5eja0f4oyin9yrqo.jpg" alt="Top products by reviews" width="554" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Top Products by Discount
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;6-in-1 Bottle Can Opener&lt;/strong&gt; tops with a 64% discount.
&lt;/li&gt;
&lt;li&gt;Heavy discounting concentrated in &lt;strong&gt;low-cost household goods&lt;/strong&gt;.
➡️ Sellers use price cuts to stimulate demand in this category.&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%2Fa2ulf3ep90h320t26dvb.jpg" 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%2Fa2ulf3ep90h320t26dvb.jpg" alt="Top product by Discount" width="575" height="237"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Correlation Analysis
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Price vs Rating:&lt;/strong&gt; Weak positive correlation (0.191426). Higher prices show a slight tendency toward better ratings, but the link is weak. &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%2Fznmwztpu0lt3jdpp1mqy.jpg" 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%2Fznmwztpu0lt3jdpp1mqy.jpg" alt="Price Vs Ratings Scatter Chart" width="485" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ratings vs Reviews:&lt;/strong&gt; Weak positive correlation (0.14671). More reviews loosely align with higher ratings, but the relationship is minimal. &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%2Fay9ty3pwlcpem3h2jdun.jpg" 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%2Fay9ty3pwlcpem3h2jdun.jpg" alt="Ratings vs reviews Scatter chart" width="518" height="214"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discount vs Reviews:&lt;/strong&gt; Weak negative correlation (-0.13682). Larger discounts are slightly associated with fewer reviews.
&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%2F2muirscgy4b2vakh8zp0.jpg" 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%2F2muirscgy4b2vakh8zp0.jpg" alt="Discount vs Reviews Scatter chart" width="587" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;➡️ Overall, none of the variables strongly predict the others.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;Test discount bands to optimize engagement without eroding margins.
&lt;/li&gt;
&lt;li&gt;Improve listing content for products with visibility but average ratings.
&lt;/li&gt;
&lt;li&gt;Investigate quality issues for highly discounted but poorly rated items.
&lt;/li&gt;
&lt;li&gt;Promote products that combine excellent ratings with strong engagement.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Limitations and Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Reviews are a proxy for engagement, not sales.
&lt;/li&gt;
&lt;li&gt;Missing values were left blank rather than imputed.
&lt;/li&gt;
&lt;li&gt;Price ranges required assumptions (midpoints).
&lt;/li&gt;
&lt;li&gt;Correlation does not imply causation — discounts may coincide with other factors like product age or visibility.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dashboard Screenshot
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Jumia Product Dashboard Screenshot&lt;/em&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa6s9m6oufnf7nhzo9uul.jpg" 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%2Fa6s9m6oufnf7nhzo9uul.jpg" alt="Jumia Dashboard" width="656" height="396"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;This project demonstrates how Excel can be used not just for reporting, but for &lt;strong&gt;data-driven decision-making in e-commerce&lt;/strong&gt;. By combining careful cleaning, structured analysis, and interactive dashboards, sellers gain practical insights into how pricing and customer feedback shape product performance.&lt;/p&gt;




</description>
      <category>tutorial</category>
      <category>tools</category>
      <category>datascience</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Getting Started with Excel for Data Analytics: From Basics to Data Cleaning</title>
      <dc:creator>Mohammed Swaleh</dc:creator>
      <pubDate>Sat, 29 Aug 2026 21:14:53 +0000</pubDate>
      <link>https://dev.to/maditech/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-4p80</link>
      <guid>https://dev.to/maditech/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-4p80</guid>
      <description>&lt;h2&gt;
  
  
  Excel Data Cleaning &amp;amp; Analysis Guide
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;Excel is more than a spreadsheet—it’s a powerful data-analysis tool. Analysts use it to inspect, validate, filter, summarize, and prepare raw data before deeper analysis.&lt;br&gt;&lt;br&gt;
The quality of insights depends on the quality of data. That’s why data cleaning is the foundation of effective analysis.&lt;/p&gt;

&lt;p&gt;This guide demonstrates Week 1 Excel concepts using an employee dataset with fields like employee IDs, names, departments, gender, hire dates, salaries, education level, and performance scores. The raw file contains common issues: inconsistent capitalization, blanks, duplicates, varying department names, and misformatted dates/currency.  &lt;/p&gt;

&lt;p&gt;By applying Excel’s formatting tools, text functions, filters, conditional formatting, numerical functions, and date functions, we transform messy data into an analysis-ready dataset.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Why Data Cleaning Matters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Garbage in, garbage out: dashboards or predictions are misleading if data is flawed.
&lt;/li&gt;
&lt;li&gt;Standardization makes datasets transparent, usable, and valuable.
&lt;/li&gt;
&lt;li&gt;Examples:

&lt;ul&gt;
&lt;li&gt;“IT”, “I.T.”, and “Information Tech” → treated as different departments unless standardized.
&lt;/li&gt;
&lt;li&gt;Duplicate employee IDs → inflate totals.
&lt;/li&gt;
&lt;li&gt;Blank performance scores → missing information.
&lt;/li&gt;
&lt;li&gt;Dates saved as text → unreliable for tenure calculations.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Best practice: keep raw data separate, create a cleaned worksheet, and document your cleaning logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Dataset &amp;amp; Initial Inspection
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dataset size: 877 employee rows (with duplicates).
&lt;/li&gt;
&lt;li&gt;Issues: inconsistent formats in IDs, names, departments, salaries, and dates.
&lt;/li&gt;
&lt;li&gt;First steps:

&lt;ul&gt;
&lt;li&gt;Autofit Column Width for readability.
&lt;/li&gt;
&lt;li&gt;Freeze top row for easier navigation.
&lt;/li&gt;
&lt;li&gt;Apply a structured cleaning process.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.1 Standardizing Employee IDs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Remove &lt;code&gt;emp-&lt;/code&gt; prefix for uniform IDs.
&lt;/li&gt;
&lt;li&gt;Use Conditional Formatting to highlight duplicates.
&lt;/li&gt;
&lt;li&gt;Action:

&lt;ul&gt;
&lt;li&gt;Delete exact duplicates.
&lt;/li&gt;
&lt;li&gt;Retain one ID if records differ.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Result: reduced dataset to 870+ entries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.2 Cleaning Names
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Apply &lt;code&gt;=PROPER(text)&lt;/code&gt; → converts names to proper case.
&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;john&lt;/code&gt; → John.
&lt;/li&gt;
&lt;li&gt;Replace raw columns with corrected values.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.3 Standardizing Departments
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Filter and rename department names for consistency.
&lt;/li&gt;
&lt;li&gt;Eliminates spelling variations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.4 Formatting Salaries &amp;amp; Bonuses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Convert to KES currency format.
&lt;/li&gt;
&lt;li&gt;Sort values for comparison.
&lt;/li&gt;
&lt;li&gt;Replace other currencies with standardized KES.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.5 Dates &amp;amp; Employment Details
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Reformat Hire Dates consistently.
&lt;/li&gt;
&lt;li&gt;Sort newest → oldest for recruitment timeline.
&lt;/li&gt;
&lt;li&gt;Standardize categorical fields: Gender, Performance Score, Marital Status, Education Level, Employee Type, Office Location, Remote Work Status.
&lt;/li&gt;
&lt;li&gt;Standardize numerical fields: Experience, Project Count, Promotion Year, Training Hours, Feedback Score.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.6 Filtering Data
&lt;/h3&gt;

&lt;p&gt;Filters allow quick inspection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Employees in IT department.
&lt;/li&gt;
&lt;li&gt;Female employees only.
&lt;/li&gt;
&lt;li&gt;Salaries &amp;gt; 80,000.
&lt;/li&gt;
&lt;li&gt;Blank performance scores.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use Number Filters for thresholds (e.g., top 10 salaries).&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Identifying Data-Quality Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Conditional Formatting
&lt;/h3&gt;

&lt;p&gt;Highlights problems without deleting data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate values.
&lt;/li&gt;
&lt;li&gt;Blank cells.
&lt;/li&gt;
&lt;li&gt;Dates before today.
&lt;/li&gt;
&lt;li&gt;Values above/below thresholds.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: Employee ID 10407 appears twice → verify before deleting.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Find &amp;amp; Replace (Ctrl + H)
&lt;/h3&gt;

&lt;p&gt;Quick fixes for repeated issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace “Finanace” → Finance.
&lt;/li&gt;
&lt;li&gt;Replace “N/A” → blank.
&lt;/li&gt;
&lt;li&gt;Replace unwanted characters in IDs.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use carefully—preview matches before replacing.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Cleaning Text with Functions
&lt;/h2&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;Purpose&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=PROPER(text)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Capitalizes first letter&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;aNNa mWANGI&lt;/code&gt; → Anna Mwangi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=LOWER(text)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Converts to lowercase&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;JAMES&lt;/code&gt; → james&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=UPPER(text)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Converts to uppercase&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;it&lt;/code&gt; → IT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  5.1 Removing Extra Spaces
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;=TRIM(A2)&lt;/code&gt; → removes leading, trailing, and repeated spaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 Measuring &amp;amp; Extracting Text
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;=LEN(text)&lt;/code&gt; → counts characters.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=LEFT(text,n)&lt;/code&gt; → extracts from left.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=RIGHT(text,n)&lt;/code&gt; → extracts from right.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=MID(text,start,n)&lt;/code&gt; → extracts middle.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=CONCAT(text1,text2,...)&lt;/code&gt; → joins text.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Numerical &amp;amp; Statistical Functions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6.1 Arithmetic Operators
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;+&lt;/code&gt; Addition
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-&lt;/code&gt; Subtraction
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*&lt;/code&gt; Multiplication
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; Division
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;^&lt;/code&gt; Exponent
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;5% salary increase → &lt;code&gt;=G2*0.05&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;New salary → &lt;code&gt;=G2+(G2*0.05)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;=SUM(range)&lt;/code&gt; → total
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=AVERAGE(range)&lt;/code&gt; → mean
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=MEDIAN(range)&lt;/code&gt; → middle value
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=MODE(range)&lt;/code&gt; → most frequent
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=MIN(range)&lt;/code&gt; → lowest
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=MAX(range)&lt;/code&gt; → highest
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Counting &amp;amp; Conditional Analysis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  7.1 Count Functions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;COUNT&lt;/code&gt; → numeric cells only.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COUNTA&lt;/code&gt; → nonblank cells.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COUNTBLANK&lt;/code&gt; → empty cells.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7.2 Conditional Counting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;COUNTIF(range,"IT")&lt;/code&gt; → IT employees.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COUNTIFS(range1,"IT",range2,"Female")&lt;/code&gt; → Female IT employees.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7.3 Conditional Aggregation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SUMIF&lt;/code&gt; → total salaries by condition.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SUMIFS&lt;/code&gt; → multiple conditions.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AVERAGEIF&lt;/code&gt; → average by condition.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AVERAGEIFS&lt;/code&gt; → average with multiple conditions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Dates &amp;amp; Time-Based Cleaning
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;=TODAY()&lt;/code&gt; → current date.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=NOW()&lt;/code&gt; → current date &amp;amp; time.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=YEAR(F2)&lt;/code&gt; → extract year.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=MONTH(F2)&lt;/code&gt; → extract month.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;=DAY(F2)&lt;/code&gt; → extract day.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.1 DATEDIF
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tenure in days → &lt;code&gt;=DATEDIF(F2,TODAY(),"d")&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Months → &lt;code&gt;"m"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Years → &lt;code&gt;"y"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.2 NETWORKDAYS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Working days between dates → &lt;code&gt;=NETWORKDAYS(F2,TODAY())&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Recommended Cleaning Workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Preserve raw data.
&lt;/li&gt;
&lt;li&gt;Copy into cleaned worksheet.
&lt;/li&gt;
&lt;li&gt;Inspect with filters &amp;amp; conditional formatting.
&lt;/li&gt;
&lt;li&gt;Identify duplicates visually.
&lt;/li&gt;
&lt;li&gt;Standardize text with TRIM, PROPER, LOWER, UPPER.
&lt;/li&gt;
&lt;li&gt;Validate text with LEN, LEFT, RIGHT, MID, CONCAT.
&lt;/li&gt;
&lt;li&gt;Check completeness with COUNT functions.
&lt;/li&gt;
&lt;li&gt;Summarize with COUNTIFS, SUMIFS, AVERAGEIFS.
&lt;/li&gt;
&lt;li&gt;Use date functions for tenure/workdays.
&lt;/li&gt;
&lt;li&gt;Review, document assumptions, then analyze.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;Data cleaning must happen before interpretation.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conditional formatting → detect issues.
&lt;/li&gt;
&lt;li&gt;Filters → inspect subsets.
&lt;/li&gt;
&lt;li&gt;Find &amp;amp; Replace → correct repeated values.
&lt;/li&gt;
&lt;li&gt;Text functions → standardize labels.
&lt;/li&gt;
&lt;li&gt;Aggregate functions → summarize numbers.
&lt;/li&gt;
&lt;li&gt;Conditional functions → reveal group patterns.
&lt;/li&gt;
&lt;li&gt;Date functions → calculate time-based insights.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following a structured workflow, analysts ensure datasets are consistent, reliable, and ready for advanced analysis like PivotTables, dashboards, and statistical modeling.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tutorial</category>
      <category>datascience</category>
      <category>analytics</category>
    </item>
    <item>
      <title>My First GitHub Project: From a Local Folder to GitHub Using Git and SSH</title>
      <dc:creator>Mohammed Swaleh</dc:creator>
      <pubDate>Sat, 22 Aug 2026 17:52:45 +0000</pubDate>
      <link>https://dev.to/maditech/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-26mn</link>
      <guid>https://dev.to/maditech/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-26mn</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I have always used the term &lt;em&gt;Git&lt;/em&gt;, &lt;em&gt;Github&lt;/em&gt; and &lt;em&gt;Git bash&lt;/em&gt; interchangeably, thinking they refer to the same thing, but I have come to learn and understand that &lt;em&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/em&gt; is an online platform on the internet where developers store and share their projects, or repositories. A &lt;em&gt;&lt;strong&gt;repository&lt;/strong&gt;&lt;/em&gt;, normally called a &lt;em&gt;repo&lt;/em&gt;, is a project being tracked by Git. &lt;em&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/em&gt; is a version control system that runs on the local computer and can be used to track checkpoints created in a project. Therefore, &lt;em&gt;Git&lt;/em&gt; is the tool used to track changes in a project, while &lt;em&gt;&lt;strong&gt;SSH&lt;/strong&gt;&lt;/em&gt;, which stands for &lt;em&gt;Secure Shell&lt;/em&gt;, provides a secure way to connect your git running on your computer to GitHub on the internet. _ Git Bash _ is a tool or an application that can be used to run Git commands&lt;/p&gt;

&lt;p&gt;This guide explains how to upload a project from a local folder on your computer to GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Create a GitHub Account&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://dev.tourl"&gt;(https://github.com/)&lt;/a&gt; and sign up for an account if you do not already have one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.tourl"&gt;(https://github.com/signup)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will normally provide your email address, password and username for the github account. After creating the account, verify your email address.&lt;/p&gt;

&lt;p&gt;After signing in, create a new repository. A repository is a storage space for your project.&lt;/p&gt;

&lt;p&gt;When creating the repository, provide a name for the repo, then click &lt;em&gt;Create repository&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Install Git on your windows PC&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First, install Git on your computer from the official Git website:&lt;/p&gt;

&lt;p&gt;[Download Git] &lt;a href="https://dev.tourl"&gt;(https://git-scm.com/downloads)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After downloading the installer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your Downloads folder.&lt;/li&gt;
&lt;li&gt;Find the downloaded Git installer.&lt;/li&gt;
&lt;li&gt;Double-click it.&lt;/li&gt;
&lt;li&gt;Allow Windows to run the installer.&lt;/li&gt;
&lt;li&gt;Go through the installation screens.&lt;/li&gt;
&lt;li&gt;For a normal beginner installation, you can generally keep the recommended/default options.&lt;/li&gt;
&lt;li&gt;Complete the installation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One important tool installed with Git for Windows is Git Bash. After installing it, open git bash and run on the command prompt to check that Git works:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If Git is installed correctly, you will see its version number.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git version 2.55.0.windows.4&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Configure Git Username and Email Address&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Next, you need to tell git your username and email address associated with your GitHub account. You type on the command prompt&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git config --global user.name "Your Full Name"&lt;/code&gt; &lt;em&gt;to configure your name&lt;/em&gt; and &lt;br&gt;
&lt;code&gt;git config --global user.email "Your Email address"&lt;/code&gt; &lt;em&gt;to configure your email&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example&lt;/em&gt;:&lt;br&gt;
&lt;code&gt;git config --global user.name "Mohammed Swaleh"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git config --global user.email mswaleh@gmail.com&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Configure main as the Default Branch
&lt;/h2&gt;

&lt;p&gt;Next, you need to Set &lt;em&gt;main&lt;/em&gt; as the Default Branch&lt;br&gt;
&lt;em&gt;Run&lt;/em&gt;:&lt;br&gt;
&lt;code&gt;git config --global init.defaultBranch main&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This tells Git to use main, as the default initial branch for new repositories.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;5. Verify Your Git Configuration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To check your name: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Type in Git Bash&lt;/em&gt;&lt;br&gt;
&lt;code&gt;git config --global user.name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To check your email:&lt;br&gt;
&lt;em&gt;type&lt;/em&gt;&lt;br&gt;
&lt;code&gt;git config --global user.email&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To check all global configuration:&lt;br&gt;
&lt;code&gt;git config --global --list&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You should see something similar to:&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;user.name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Mohammed Swaleh&lt;/span&gt;
&lt;span class="py"&gt;user.email&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mswaleh@gmail.com&lt;/span&gt;
&lt;span class="py"&gt;init.defaultbranch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;6. Set Up Secure Shell (SSH)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;SSH allows Git to connect securely to your GitHub account without asking for your password every time.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Confirm SSH key exists&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Open your terminal and check whether SSH key exists&lt;br&gt;
&lt;em&gt;Type&lt;/em&gt;&lt;br&gt;
&lt;code&gt;ls -al ~/.ssh&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can see&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;id_ed25519
id_ed25519.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;or older files such as:&lt;br&gt;
&lt;code&gt;id_rsa&lt;br&gt;
id_rsa.pub&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;if you encounter this error message:&lt;br&gt;
&lt;code&gt;No such file or directory&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This means that the SSH key does not exist and you need to create an SSH key&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Create an SSH key&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Type in the terminal:&lt;br&gt;
&lt;code&gt;ssh-keygen -t ed25519 -C "your_email@example.com"&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Replace:&lt;br&gt;
&lt;em&gt;&lt;a href="mailto:your_email@example.com"&gt;your_email@example.com&lt;/a&gt;&lt;/em&gt;, with the &lt;em&gt;email&lt;/em&gt; associated with your &lt;em&gt;GitHub account&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;code&gt;ssh-keygen -t ed25519 -C "mswaleh@gmail.com"&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Press &lt;em&gt;Enter&lt;/em&gt; to accept the suggested file location. You can also create a passphrase for extra security.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Confirm That the Key Was Created&lt;/strong&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;type:&lt;br&gt;
&lt;code&gt;ls -al ~/.ssh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should now see:&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;id_ed25519
id_ed25519.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;7. ADD THE private SSH KEY TO THE SSH AGENT&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The SSH agent helps manage your private SSH key and can remember its passphrase during your session. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To Start the SSH Agent for windows, &lt;br&gt;
&lt;em&gt;open&lt;/em&gt;:&lt;br&gt;
&lt;em&gt;PowerShell, as Administrator.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the powershell terminal, &lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;code&gt;Get-Service -Name ssh-agent | Set-Service -StartupType Manual&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Start-Service ssh-agent&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Exit powershell as an &lt;em&gt;administrator&lt;/em&gt;, open powershell as a &lt;em&gt;normal user&lt;/em&gt;,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Type:&lt;br&gt;
&lt;code&gt;ssh-add c:/Users/YOUR_USERNAME/.ssh/id_ed25519&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Replace:&lt;br&gt;
&lt;em&gt;YOUR_USERNAME&lt;/em&gt; with your actual Windows username.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;code&gt;ssh-add c:/Users/mswaleh/.ssh/id_ed25519&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you do not know your Windows username, you can run:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;whoami&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You may receive something like:&lt;br&gt;
&lt;code&gt;DESKTOP-12345\mswaleh&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your username is therefore, in this example:&lt;br&gt;
&lt;code&gt;mswaleh&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;8. Windows — Copy the Public SSH Key&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Open Git Bash.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Run&lt;br&gt;
&lt;code&gt;cat ~/.ssh/id_ed25519.pub | clip&lt;/code&gt;&lt;br&gt;
The public key should now be in your clipboard.&lt;/p&gt;

&lt;p&gt;If that does not work, display it:&lt;br&gt;
&lt;code&gt;cat ~/.ssh/id_ed25519.pub&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will see one long line similar to:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... mswaleh@gmail.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Copy the entire line.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;9. ADD THE SSH KEY TO GITHUB&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;On GitHub:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click your profile picture.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Settings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;SSH and GPG keys&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New SSH key&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Give the key a name.&lt;/li&gt;
&lt;li&gt;Paste your public key.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add SSH key&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GitHub may ask you to confirm your email account.&lt;br&gt;
Complete the confirmation.&lt;br&gt;
Your SSH public key should then appear in your GitHub account.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;10. TEST THE SSH CONNECTION&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Test GitHub SSH Authentication&lt;br&gt;
Return to:&lt;br&gt;
Git Bash on Windows,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Run:&lt;br&gt;
&lt;code&gt;ssh -T git@github.com&lt;/code&gt;&lt;br&gt;
If everything is correctly configured, you should get a message similar to:&lt;/p&gt;

&lt;p&gt;Hi YOUR_USERNAME! You've successfully authenticated, but GitHub does not provide shell access. This is a success message.&lt;br&gt;
It means:&lt;br&gt;
Computer&lt;br&gt;
↓&lt;br&gt;
Private SSH Key&lt;br&gt;
↓&lt;br&gt;
GitHub verifies the public key&lt;br&gt;
↓&lt;br&gt;
Authentication Successful&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;11. Open Your Local Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Use the terminal to move into your project folder.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;cd path/to/your-project&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can check the files in the folder with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ls&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;12. Turn the Folder Into a Git Repository&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Inside the project folder, run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This creates a hidden &lt;code&gt;.git&lt;/code&gt; folder. Git uses this folder to track changes in your project.&lt;/p&gt;

&lt;p&gt;Now check the status of your files:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git status&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;13. Add a README File&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;README file&lt;/em&gt; explains what your project is about. Create a file called &lt;em&gt;README.md&lt;/em&gt; and write a short description.&lt;/p&gt;

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


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# My First GitHub Project&lt;/span&gt;

This is my first project uploaded to GitHub using Git and SSH.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;14. Save Your Files in Git&lt;/strong&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Add all project files:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The period means "add all files in this folder".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create your first commit:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git commit -m "Initial commit"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A commit is a saved version of your project. The message explains what was changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;15. Connect the Local Folder to GitHub&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;On your GitHub repository page, copy the SSH address. It will look similar to this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git@github.com:your-username/your-repository.git&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Connect your local project to the GitHub repository:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;git remote add origin git@github.com:your-username/your-repository.git&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can check the connection with:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;git remote -v&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;16. Upload the Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Rename your main branch to &lt;em&gt;main&lt;/em&gt;:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;git branch -M main&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Then upload the project to GitHub:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;git push -u origin main&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;push&lt;/em&gt;  command sends your committed files from your computer to GitHub.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Refresh your GitHub repository page. Your project files should now be visible online.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;17. Updating the Project Later&lt;/strong&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Whenever you make changes, use these three commands:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Describe your changes"&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add homepage design"&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This saves the new changes locally and uploads them to GitHub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;18. Common Problems&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;GitHub rejects the push&lt;/strong&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure the repository address is correct:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;git remote -v&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can replace the incorrect address with:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;git remote set-url origin git@github.com:your-username/your-repository.git&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;SSH permission denied&lt;/strong&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Check that your SSH key has been added to GitHub and test the connection again:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;ssh -T git@github.com&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Files are not uploaded&lt;/strong&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Check the repository status:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;git status&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Then add, commit, and push the files:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add project files"&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Final Git Workflow&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The basic workflow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;
git remote add origin git@github.com:your-username/your-repository.git
git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;After the first upload, you usually only need:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Describe your changes"&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Moving a project from a local folder to GitHub may seem difficult at first, but the process becomes simple with practice. Git tracks your work, GitHub stores it online, and SSH provides a secure connection between your computer and your GitHub account.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>git</category>
    </item>
  </channel>
</rss>
