<?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: Miss Analyst</title>
    <description>The latest articles on DEV Community by Miss Analyst (@mwatela_nazi_d1d2cd301ba1).</description>
    <link>https://dev.to/mwatela_nazi_d1d2cd301ba1</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%2F3958644%2Fc46e8add-ef4e-4621-a20f-b4108f44a1da.png</url>
      <title>DEV Community: Miss Analyst</title>
      <link>https://dev.to/mwatela_nazi_d1d2cd301ba1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mwatela_nazi_d1d2cd301ba1"/>
    <language>en</language>
    <item>
      <title>SQL Functions — A Friendly Guide With Real Examples</title>
      <dc:creator>Miss Analyst</dc:creator>
      <pubDate>Mon, 07 Sep 2026 16:32:39 +0000</pubDate>
      <link>https://dev.to/mwatela_nazi_d1d2cd301ba1/sql-functions-a-friendly-guide-with-real-examples-4lbo</link>
      <guid>https://dev.to/mwatela_nazi_d1d2cd301ba1/sql-functions-a-friendly-guide-with-real-examples-4lbo</guid>
      <description>&lt;p&gt;When I was learning SQL, "functions" felt like a big scary word borrowed from programming. Turns out, they're just small helpers that do one job: take some data in, give you a changed version back out. Once that clicked, SQL got a lot less intimidating.&lt;/p&gt;

&lt;p&gt;This article walks through the SQL functions you'll actually use, with real examples — an online store, a user table, a sales report — and notes on when each one is the right tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a SQL Function?
&lt;/h2&gt;

&lt;p&gt;Think of a function as a little machine. You feed it something (a column, a number, a piece of text), and it hands back a result. You don't need to know how it works inside, you just need to know what it takes in and what it gives back.&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="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&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;customers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;UPPER&lt;/code&gt; is the machine. Feed it a name, it hands back the name in capital letters. That's the whole idea behind every function in this article.&lt;/p&gt;

&lt;p&gt;SQL functions generally fall into a few groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aggregate functions&lt;/strong&gt; — take many rows and turn them into one answer (like a total or an average).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;String functions&lt;/strong&gt; — work on text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date/time functions&lt;/strong&gt; — work on dates and times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Numeric functions&lt;/strong&gt; — do math.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Window functions&lt;/strong&gt; — a bit more advanced, but incredibly useful once you get them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's go through each with  examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Aggregate Functions
&lt;/h2&gt;

&lt;p&gt;They look at a group of rows and give you back a single number.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;COUNT()&lt;/code&gt; — how many?
&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="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;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used any time you're asking "how many of these are there?" — how many orders came in today, how many users signed up this month, how many products are out of stock.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SUM()&lt;/code&gt; — add it all up
&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="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_total&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;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;order_date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2026-09-01'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used when calculating  totals example; total revenue this month, total items sold, total hours logged.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;AVG()&lt;/code&gt; — the average
&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="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_total&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;orders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used anytime "on average" comes up in a question. It could be average order size, average time to respond to a support ticket or average rating on a product.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;MIN()&lt;/code&gt; and &lt;code&gt;MAX()&lt;/code&gt; — the smallest and biggest
&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="k"&gt;MIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_total&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;cheapest&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;order_total&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;priciest&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used when finding extremes like the cheapest order ever placed, the newest signup, the oldest unpaid invoice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grouping it all together with &lt;code&gt;GROUP BY&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Aggregate functions get really useful once you pair them with &lt;code&gt;GROUP BY&lt;/code&gt;. Say you want total sales &lt;em&gt;per month&lt;/em&gt;, not just one giant total:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;DATE_TRUNC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'month'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;month&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;order_total&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_sales&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;order_count&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&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;Used with  basically any report. "Sales by month," "orders by customer," "signups by country" all of these are a &lt;code&gt;GROUP BY&lt;/code&gt; with one or more aggregate functions attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  2.String Functions
&lt;/h2&gt;

&lt;p&gt;Text is messy. People type names in weird cases, leave extra spaces, or you need to combine two columns into one readable label. String functions clean this up.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;CONCAT()&lt;/code&gt; — joining text together
&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;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&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;full_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is used when building a display name, combining an address from separate columns, making a readable label out of pieces of data.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;UPPER()&lt;/code&gt; and &lt;code&gt;LOWER()&lt;/code&gt; — changing case
&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;email&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'jane@example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used when comparing text without worrying about capital letters. This is a common one, someone might type &lt;code&gt;Jane@Example.com&lt;/code&gt; at signup, and you still want to match it against &lt;code&gt;jane@example.com&lt;/code&gt; later.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;TRIM()&lt;/code&gt; — removing extra spaces
&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="k"&gt;TRIM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coupon_code&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;orders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used when cleaning up data that came from a form or an import file, where people (or systems) often leave a stray space at the start or end.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;LENGTH()&lt;/code&gt; — how long is this text?
&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;name&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;LENGTH&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&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;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used when catching data problems, like a product name that's way too long to display properly, or a password that's too short.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SUBSTRING()&lt;/code&gt; — grabbing part of a text value
&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="k"&gt;SUBSTRING&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;area_code&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use it when pulling out a piece of a larger value, like an area code from a phone number, or the first few letters of a product code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;REPLACE()&lt;/code&gt; — swapping text
&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="k"&gt;REPLACE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'St.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Street'&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;customers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can be used when fixing inconsistent data, like standardizing abbreviations before generating a report.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.Date and Time Functions
&lt;/h2&gt;

&lt;p&gt;Dates come up constantly: "when did this happen," "how long ago was that," "what month was this in." These functions make dates usable.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;NOW()&lt;/code&gt; / &lt;code&gt;CURRENT_DATE&lt;/code&gt; — right now
&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;subscriptions&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;renewal_date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;CURRENT_DATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;anything that depends on "today" — overdue payments, expired trials, upcoming renewals.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;DATE_TRUNC()&lt;/code&gt; — rounding a date down to a unit
&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;DATE_TRUNC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'month'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signup_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;signup_month&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;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&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;We can use it when grouping data by day, week, or month. This is one of the most useful functions for building reports — it turns a messy timestamp into a clean bucket you can group by.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;DATEDIFF()&lt;/code&gt; / date subtraction — how much time passed
&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CURRENT_DATE&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;signup_date&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;days_since_signup&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Note: the exact syntax for this varies a bit by database — Postgres lets you subtract dates directly like above, while MySQL and SQL Server use &lt;code&gt;DATEDIFF()&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;Used to calculating someone's account age, how many days a task has been open, or how long it's been since a customer's last order.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;EXTRACT()&lt;/code&gt; — pulling out one piece of a date
&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="k"&gt;EXTRACT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DOW&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;order_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;day_of_week&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;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&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;Used when finding patterns, like "do we get more orders on weekends?" &lt;code&gt;DOW&lt;/code&gt; here means day of week.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Numeric Functions — Basic Math
&lt;/h2&gt;

&lt;p&gt;These are the functions you reach for when you need to do a bit of arithmetic inside your query, instead of after the fact.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ROUND()&lt;/code&gt; — rounding numbers
&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;ROUND&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;order_total&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;avg_order&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used when cleaning up decimals for a report. Nobody wants to see &lt;code&gt;47.836218&lt;/code&gt; when &lt;code&gt;47.84&lt;/code&gt; is what actually matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ABS()&lt;/code&gt; — absolute value
&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="k"&gt;ABS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balance&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;balance_owed&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used when working with numbers that can be negative, like a balance or a difference, when you just care about the size of the number, not the sign.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Window Functions
&lt;/h2&gt;

&lt;p&gt;Window functions look a bit different, they solve problems that are painful otherwise unlike aggregate functions, they don't collapse rows into one — they add a calculated value &lt;em&gt;next to&lt;/em&gt; each row.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ROW_NUMBER()&lt;/code&gt; — numbering rows
&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;order_total&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;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;order_total&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;rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used when ranking things, like "who are our top 10 spenders" or "what's the 3rd most recent order for each customer."&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;RANK()&lt;/code&gt; and &lt;code&gt;DENSE_RANK()&lt;/code&gt; — ranking with ties
&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;score&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;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;score&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;rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;quiz_results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;example — "top order per customer"&lt;/p&gt;

&lt;p&gt;Say you want each customer's biggest order, but you still want to see their name and every order next to it:&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="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;order_total&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;customer_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;order_total&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;rn&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ranked&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;rn&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;Used anytime you want "the top result per group", the newest order per customer, the highest score per student, the latest login per user. This is genuinely hard to do without a window function, and once you learn this pattern, you'll reuse it constantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;SQL functions aren't complicated once you see them as small, single-purpose helpers. Aggregate functions turn many rows into one number. String functions clean up and shape text. Date functions make "when" usable. Window functions let you rank and compare rows without losing the details.&lt;/p&gt;

&lt;p&gt;You don't need to memorize all of them right away. Start with &lt;code&gt;COUNT&lt;/code&gt;, &lt;code&gt;SUM&lt;/code&gt;, &lt;code&gt;AVG&lt;/code&gt;, and &lt;code&gt;DATE_TRUNC&lt;/code&gt;, you'll use those constantly. The rest will stick as you run into the problems they solve&lt;/p&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>SUBQUERIES AND CTEs</title>
      <dc:creator>Miss Analyst</dc:creator>
      <pubDate>Mon, 07 Sep 2026 15:54:55 +0000</pubDate>
      <link>https://dev.to/mwatela_nazi_d1d2cd301ba1/subqueries-and-ctes-5g4i</link>
      <guid>https://dev.to/mwatela_nazi_d1d2cd301ba1/subqueries-and-ctes-5g4i</guid>
      <description>&lt;p&gt;When I first started learning SQL, writing a basic SELECT query wasn't too bad.&lt;br&gt;
Then came questions like:&lt;/p&gt;

&lt;p&gt;"What if I need to use the result of one query inside another query?"&lt;/p&gt;

&lt;p&gt;That's where subqueries come in.&lt;br&gt;
And when those queries start getting longer and harder to read, you might come across something called a CTE.&lt;br&gt;
At first, both can seem confusing. But once you understand what they're doing, they actually make a lot of sense.&lt;/p&gt;

&lt;p&gt;In this article, I'll break down subqueries and CTEs using simple examples and explain when you might want to use each one.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Is a Subquery?
&lt;/h2&gt;

&lt;p&gt;A subquery is simply a query inside another query. Instead of running two completely separate queries, we can put one query inside another and use its result.&lt;/p&gt;

&lt;p&gt;Here's where they tend to show up in real code.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Inside a &lt;code&gt;WHERE&lt;/code&gt; clause — "find rows above or below some number"
&lt;/h3&gt;

&lt;p&gt;Say you run a small online store. You want to find your best customers: people who spent more than the average.&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;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;lifetime_spend&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;lifetime_spend&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;customers&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The inner query gives back one number: the average. The outer query uses that number as a cutoff. You'll see this pattern everywhere — flagging a payment that's way above someone's usual spend, or a product selling faster than others in its category.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Inside a &lt;code&gt;FROM&lt;/code&gt; clause — using a query result like a table
&lt;/h3&gt;

&lt;p&gt;Say your marketing team wants the average order value per city, but only for cities where that average is above $50.&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;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;avg_order_value&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;city&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;order_total&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;avg_order_value&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&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;city&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;city_averages&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;avg_order_value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This inner query builds a small, temporary table, and the outer query filters it. You can't filter on &lt;code&gt;avg_order_value&lt;/code&gt; in the same step where you calculate it, so this two-step approach is what lets you do it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Inside a &lt;code&gt;SELECT&lt;/code&gt; clause — pulling in one extra fact per row
&lt;/h3&gt;

&lt;p&gt;Say someone asks: "next to each customer's name, show how many orders they've placed."&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;name&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;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;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;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;order_count&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This only works if the subquery returns exactly one number per row. It's fine for small cases like this, but if you're doing it across a lot of rows, a &lt;code&gt;JOIN&lt;/code&gt; is usually the faster choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Correlated subqueries — when the inner query needs the outer row
&lt;/h3&gt;

&lt;p&gt;A correlated subquery looks at the current row from the outer query while it runs. It can't run on its own — it runs once for every row.&lt;/p&gt;

&lt;p&gt;Say you want to find employees who earn more than the average salary &lt;em&gt;in their own department&lt;/em&gt; (not the whole company).&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;e1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;salary&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;e2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;salary&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;employees&lt;/span&gt; &lt;span class="n"&gt;e2&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;e2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See that line, &lt;code&gt;e2.department = e1.department&lt;/code&gt;? That's the connection back to the outer row. For each employee, the subquery works out the average pay for just their department. This kind of check is hard to write any other way, which is exactly when a subquery is the right call.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a CTE?
&lt;/h2&gt;

&lt;p&gt;A CTE (short for Common Table Expression) is a named subquery placed at the top of your query, using &lt;code&gt;WITH&lt;/code&gt;. Same result, easier to read.&lt;/p&gt;

&lt;p&gt;Here's the "cities with above-average order value" example again, written as 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;WITH&lt;/span&gt; &lt;span class="n"&gt;city_averages&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;city&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;order_total&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;avg_order_value&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&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;city&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;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;avg_order_value&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;city_averages&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;avg_order_value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does the exact same thing as the earlier version. But read it out loud: "with city averages as this, select from city averages where..." It sounds close to plain English. That's the main reason people like CTEs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chaining CTEs together
&lt;/h3&gt;

&lt;p&gt;This is where CTEs really help. Say you're building a dashboard and want to know which cities have the most big-spending customers.&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;big_spenders&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;lifetime_spend&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;big_spenders_by_city&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;city&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;spender_count&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_spenders&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;city&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;big_spenders_by_city&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;spender_count&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;Each step has a name, and each step builds on the one before it. Try writing this with nested subqueries instead, and you'll end up with closing brackets stacked on top of each other. Nobody enjoys reading that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recursive CTEs — the one thing subqueries can't do
&lt;/h3&gt;

&lt;p&gt;This is the real strength of CTEs. Recursive CTEs handle anything shaped like a tree: org charts, product categories (like "Electronics &amp;gt; Laptops &amp;gt; Gaming Laptops"), comment threads with replies to replies.&lt;/p&gt;

&lt;p&gt;Here's an org chart example — showing who reports to who, all the way down.&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;org_chart&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&gt;-- Start at the top: anyone with no manager&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;manager_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;level&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;manager_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="k"&gt;UNION&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt;

  &lt;span class="c1"&gt;-- Then find everyone who reports to someone we already found&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;manager_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;oc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;level&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;org_chart&lt;/span&gt; &lt;span class="n"&gt;oc&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;manager_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;org_chart&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;level&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It starts at the top of the company, then keeps adding the next level down, one step at a time, until there's nobody left to add. Without a recursive CTE, you'd need to write a loop in your app code to do this.&lt;/p&gt;

&lt;p&gt;A product category tree works almost the same way. Just swap &lt;code&gt;manager_id&lt;/code&gt; for &lt;code&gt;parent_category_id&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;WITH&lt;/span&gt; &lt;span class="k"&gt;RECURSIVE&lt;/span&gt; &lt;span class="n"&gt;category_tree&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent_category_id&lt;/span&gt;&lt;span class="p"&gt;,&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;depth&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;parent_category_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="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="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent_category_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;depth&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;categories&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
  &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;category_tree&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent_category_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;category_tree&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;depth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same pattern, different data. Once you see it once, you'll notice it everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subquery vs CTE: Quick Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Subquery&lt;/th&gt;
&lt;th&gt;CTE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Can you reuse it in the same query?&lt;/td&gt;
&lt;td&gt;No, you'd have to write it again&lt;/td&gt;
&lt;td&gt;Yes, just reference its name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easy to read when there are many steps?&lt;/td&gt;
&lt;td&gt;Gets messy fast&lt;/td&gt;
&lt;td&gt;Stays readable, step by step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can it repeat itself (recursion)?&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes, with &lt;code&gt;WITH RECURSIVE&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can it use the outer row for context?&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Not directly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  "But Which One Is Faster?"
&lt;/h2&gt;

&lt;p&gt;People ask this a lot, so let's settle it: there's no single right answer. Be careful trusting anyone who claims one is always faster.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Older versions of Postgres (before version 12) always computed a CTE fully before using it, even if you only needed a few rows out of it. That gave CTEs a bad reputation. Postgres 12 and later fixed this.&lt;/li&gt;
&lt;li&gt;In SQL Server, MySQL 8+, and modern Postgres, a CTE and an equivalent subquery are usually treated the same way by the database, with the same speed.&lt;/li&gt;
&lt;li&gt;Recursive CTEs aren't really part of this comparison, since there's no subquery way to repeat a query like that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't choose based on an old rumor about speed. Choose based on what's easier to read. If speed really matters for a specific query, check the real execution plan instead of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, Which One Should You Use?
&lt;/h2&gt;

&lt;p&gt;Most of the time it comes down to how many steps your query needs. Here's a simple way to decide:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use a subquery when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's a small, one-off check, like "only show rows above the average."&lt;/li&gt;
&lt;li&gt;Giving it a name would be more effort than it's worth.&lt;/li&gt;
&lt;li&gt;It needs to use the current row from the outer query (a correlated subquery).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use a CTE when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your query has more than one step, and naming each step makes it easier to follow.&lt;/li&gt;
&lt;li&gt;You need to use the same result more than once in your query.&lt;/li&gt;
&lt;li&gt;You're working with tree-shaped data, like org charts or categories.&lt;/li&gt;
&lt;li&gt;You're debugging and want to check one step at a time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Both Together (This Is Normal)
&lt;/h2&gt;

&lt;p&gt;Most real queries mix the two. A CTE handles the overall structure, and a small subquery handles a quick check inside it. Here's a monthly sales report that does both:&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;monthly_sales&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;DATE_TRUNC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'month'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;total_sales&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
  &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&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;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;total_sales&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;total_sales&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_sales&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;monthly_sales&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;diff_from_avg&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;monthly_sales&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;month&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CTE groups sales by month. The small subquery at the end compares each month to the average. Simple, and easy to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Subqueries and CTEs both do similar work, and most SQL developers use both, depending on the situation. Any CTE without recursion could technically be written as a subquery instead — but that doesn't mean it should be. If your query has several steps, let a CTE lay them out clearly. If you just need one quick check, a subquery works fine. And if your data is shaped like a tree, a recursive CTE is really your only option.&lt;/p&gt;

&lt;p&gt;The best test isn't "which one is technically correct." It's "can I read this again in six months without getting confused." Aim for that, and you'll be fine.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>database</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding Relationship Schemas and Joins in Power BI</title>
      <dc:creator>Miss Analyst</dc:creator>
      <pubDate>Mon, 07 Sep 2026 13:08:04 +0000</pubDate>
      <link>https://dev.to/mwatela_nazi_d1d2cd301ba1/understanding-relationship-schemas-and-joins-in-power-bi-3e9l</link>
      <guid>https://dev.to/mwatela_nazi_d1d2cd301ba1/understanding-relationship-schemas-and-joins-in-power-bi-3e9l</guid>
      <description>&lt;p&gt;When I first started learning databases, I honestly found the terminology a little overwhelming.&lt;/p&gt;

&lt;p&gt;There were so many words being thrown around — schemas, primary keys, foreign keys, relationships, joins, normalization — and at first, they all seemed like separate things I had to memorize.&lt;/p&gt;

&lt;p&gt;But after working with SQL and creating actual tables, I started realizing that these concepts are all connected.&lt;/p&gt;

&lt;p&gt;So in this article, I want to explain them in the simplest way possible, especially for anyone who is just getting started with databases. Let us start by knowing what data modelling is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DATA MODELLING&lt;/strong&gt;&lt;br&gt;
Data modeling is the process of deciding:&lt;/p&gt;

&lt;p&gt;What information do we need?&lt;br&gt;
What tables should we create?&lt;br&gt;
What should each table contain?&lt;br&gt;
How should the tables be connected?&lt;/p&gt;

&lt;p&gt;For example, if I were designing a database for a university, I might need information about:&lt;/p&gt;

&lt;p&gt;Students&lt;br&gt;
Departments&lt;br&gt;
Courses&lt;br&gt;
Lecturers&lt;br&gt;
Enrollments&lt;/p&gt;

&lt;p&gt;I wouldn't want to throw all of that information into one giant table. That would quickly become messy and difficult to manage.&lt;br&gt;
Instead, I'd create separate tables and connect them.&lt;/p&gt;

&lt;p&gt;Students&lt;br&gt;
Departments&lt;br&gt;
Courses&lt;br&gt;
Lecturers&lt;br&gt;
Enrollments&lt;/p&gt;

&lt;p&gt;That's the beginning of a data model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Is a SCHEMA&lt;/strong&gt;&lt;br&gt;
Once we've decided how we want our database to look, we need to actually define its structure.&lt;br&gt;
That's where a schema comes in.&lt;/p&gt;

&lt;p&gt;A database schema describes what exists in our database.&lt;br&gt;
It can include:&lt;/p&gt;

&lt;p&gt;Tables&lt;br&gt;
Columns&lt;br&gt;
Data types&lt;br&gt;
Primary keys&lt;br&gt;
Foreign keys&lt;br&gt;
Constraints&lt;br&gt;
Relationships&lt;/p&gt;

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

&lt;p&gt;CREATE TABLE departments (&lt;br&gt;
    department_id INT PRIMARY KEY,&lt;br&gt;
    department_name VARCHAR(100)&lt;br&gt;
);&lt;br&gt;
We're telling the database to create a table called departments and give it these two columns where  department_id is the primary key.&lt;/p&gt;

&lt;p&gt;The difference between data modelling and the schema is that; data modeling is the plan, the schema is the structure we actually create from that plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PRIMARY KEYS&lt;/strong&gt;&lt;br&gt;
A primary key is basically a unique identifier for each record in a table.&lt;/p&gt;

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

&lt;pre&gt; 
student_id  name
101        Alice
102       Brian
103       Carol
&lt;/pre&gt;  

&lt;p&gt;Here, student_id is the primary key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FOREIGN KEYS&lt;/strong&gt;&lt;br&gt;
 Where Tables Start Connecting&lt;br&gt;
Let's say we have a departments table:&lt;/p&gt;

&lt;p&gt;department_id   department_name&lt;br&gt;
1           Data Science&lt;br&gt;
2           Computer Science&lt;/p&gt;

&lt;p&gt;And we have our students table:&lt;/p&gt;

&lt;p&gt;student_id  name    department_id&lt;br&gt;
101        Alice            1&lt;br&gt;
102        Brian            2&lt;br&gt;
103        Carol            1&lt;/p&gt;

&lt;p&gt;Both tables have department_id.&lt;br&gt;
In the departments table, it's the primary key.&lt;br&gt;
In the students table, it's a foreign key.&lt;/p&gt;

&lt;p&gt;departments&lt;br&gt;
department_id (PK)&lt;br&gt;
       ↑&lt;br&gt;
       |&lt;br&gt;
       |&lt;br&gt;
students&lt;br&gt;
department_id (FK)&lt;/p&gt;

&lt;p&gt;Hence we are allowed to say:&lt;br&gt;
Alice belongs to Data Science.&lt;br&gt;
Brian belongs to Computer Science.&lt;br&gt;
Carol belongs to Data Science.&lt;/p&gt;

&lt;p&gt;The foreign key is basically helping us connect the information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding RELATIONSHIPS&lt;/strong&gt;&lt;br&gt;
 You need to understand how tables  relate to each other, there are three main relationships which are;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. One-to-One (1:1)&lt;/strong&gt;&lt;br&gt;
This means one record is connected to one record.&lt;br&gt;
For example:&lt;/p&gt;

&lt;p&gt;Person → Passport&lt;/p&gt;

&lt;p&gt;One person has one passport.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. One-to-Many (1)&lt;/strong&gt;&lt;br&gt;
It means one record in one table can be connected to many records in another table.&lt;/p&gt;

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

&lt;p&gt;Department → Students&lt;/p&gt;

&lt;p&gt;One department can have many students.&lt;/p&gt;

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

&lt;p&gt;Data Science&lt;br&gt;
     |&lt;br&gt;
     ├── Alice&lt;br&gt;
     ├── Carol&lt;br&gt;
     └── David&lt;/p&gt;

&lt;p&gt;So we have:&lt;/p&gt;

&lt;p&gt;One department → Many students&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Many-to-Many (M)&lt;/strong&gt;&lt;br&gt;
Here one record can be connected to many records and the same record can also be connected to many records take an instance&lt;br&gt;
students and courses.&lt;/p&gt;

&lt;p&gt;One student can take many courses and at the same time, one course can have many students.&lt;br&gt;
So:&lt;/p&gt;

&lt;p&gt;Students ↔ Courses&lt;/p&gt;

&lt;p&gt;That's a many-to-many relationship.&lt;/p&gt;

&lt;p&gt;We usually handle this by creating another table in between.&lt;br&gt;
This is often called a junction table or bridge table.&lt;/p&gt;

&lt;p&gt;** What  Is a JOIN?**&lt;br&gt;
A JOIN allows us to combine information from different tables.&lt;br&gt;
For example, our students table only tells us the department ID:&lt;/p&gt;

&lt;p&gt;student_id  name    department_id&lt;br&gt;
101         Alice   1&lt;br&gt;
102         Brian   2&lt;br&gt;
103         Carol   1&lt;/p&gt;

&lt;p&gt;But what if I want to see the actual department name?&lt;br&gt;
That's where a JOIN comes in.&lt;/p&gt;

&lt;p&gt;SELECT&lt;br&gt;
    students.name,&lt;br&gt;
    departments.department_name&lt;br&gt;
FROM students&lt;br&gt;
JOIN departments&lt;br&gt;
    ON students.department_id = departments.department_id;&lt;/p&gt;

&lt;p&gt;The result would look something like:&lt;/p&gt;

&lt;p&gt;name    department_name&lt;br&gt;
Alice   Data Science&lt;br&gt;
Brian   Computer Science&lt;br&gt;
Carol   Data Science&lt;/p&gt;

&lt;p&gt;The part I really want to pay attention to is:&lt;/p&gt;

&lt;p&gt;ON students.department_id = departments.department_id&lt;/p&gt;

&lt;p&gt;This tells SQL:&lt;br&gt;
"These are the columns I want you to use to connect these two tables."&lt;br&gt;
Once I understood that, JOINs became much easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types of JOINs&lt;/strong&gt;&lt;br&gt;
There are several types of JOINs, but let's focus on the main ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;INNER JOIN&lt;/strong&gt;&lt;br&gt;
An INNER JOIN gives you only the records that have a match in both tables.&lt;/p&gt;

&lt;p&gt;SELECT *&lt;br&gt;
FROM students&lt;br&gt;
INNER JOIN departments&lt;br&gt;
ON students.department_id = departments.department_id;&lt;/p&gt;

&lt;p&gt;Think of it as:&lt;/p&gt;

&lt;p&gt;"Show me the records that match."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LEFT JOIN&lt;/strong&gt;&lt;br&gt;
A LEFT JOIN keeps everything from the table on the left, even when there isn't a matching record on the right.&lt;/p&gt;

&lt;p&gt;SELECT *&lt;br&gt;
FROM students&lt;br&gt;
LEFT JOIN departments&lt;br&gt;
ON students.department_id = departments.department_id;&lt;/p&gt;

&lt;p&gt;The easiest way to remember it:&lt;/p&gt;

&lt;p&gt;LEFT JOIN = Keep everything on the left.&lt;/p&gt;

&lt;p&gt;So if there's a student without a matching department, that student can still appear in the results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RIGHT JOIN&lt;/strong&gt;&lt;br&gt;
A RIGHT JOIN is basically the opposite.&lt;br&gt;
It keeps everything from the table on the right.&lt;/p&gt;

&lt;p&gt;SELECT *&lt;br&gt;
FROM students&lt;br&gt;
RIGHT JOIN departments&lt;br&gt;
ON students.department_id = departments.department_id;&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;p&gt;RIGHT JOIN = Keep everything on the right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FULL OUTER JOIN&lt;/strong&gt;&lt;br&gt;
A FULL OUTER JOIN keeps everything from both tables.&lt;/p&gt;

&lt;p&gt;SELECT *&lt;br&gt;
FROM students&lt;br&gt;
FULL OUTER JOIN departments&lt;br&gt;
ON students.department_id = departments.department_id;&lt;/p&gt;

&lt;p&gt;It includes matching records as well as records that don't have a match.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CROSS JOIN&lt;/strong&gt;&lt;br&gt;
This one is a little different.&lt;br&gt;
A CROSS JOIN creates every possible combination between two tables.&lt;br&gt;
For example, if we have:&lt;br&gt;
3 students&lt;br&gt;
4 courses&lt;/p&gt;

&lt;p&gt;We would get:&lt;/p&gt;

&lt;p&gt;3 × 4 = 12 combinations&lt;/p&gt;

&lt;p&gt;The query would be:&lt;/p&gt;

&lt;p&gt;SELECT *&lt;br&gt;
FROM students&lt;br&gt;
CROSS JOIN courses;&lt;/p&gt;

&lt;p&gt;It's not something you'll use every day, but it's good to know what it does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relationship vs JOIN&lt;/strong&gt;&lt;br&gt;
A relationship describes how tables are connected in the database.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
Department 1 ───────&amp;lt; Students&lt;/p&gt;

&lt;p&gt;This tells us that one department can have many students.&lt;/p&gt;

&lt;p&gt;A JOIN, on the other hand, is something we use in an SQL query to actually bring information from those tables together.&lt;br&gt;
For example:&lt;/p&gt;

&lt;p&gt;SELECT *&lt;br&gt;
FROM departments&lt;br&gt;
JOIN students&lt;br&gt;
ON departments.department_id = students.department_id;&lt;/p&gt;

&lt;p&gt;So the easiest way to remember it is:&lt;br&gt;
Relationship = how the tables are connected.&lt;br&gt;
JOIN = how we retrieve data from those connected tables.&lt;/p&gt;

&lt;p&gt;Where Does Normalization Come In?&lt;br&gt;
Another term you'll probably hear a lot when learning databases is normalization.&lt;br&gt;
The basic idea is to organize your data so that you're not unnecessarily repeating the same information everywhere.&lt;/p&gt;

&lt;p&gt;For example, imagine having:&lt;/p&gt;

&lt;p&gt;student department  lecturer&lt;br&gt;
Alice   Data Science    Mr. John&lt;br&gt;
Brian   Data Science    Mr. John&lt;br&gt;
Carol   Data Science    Mr. John&lt;/p&gt;

&lt;p&gt;There's a lot of repeated information.Instead, we can separate the information into different tables and connect them.&lt;/p&gt;

&lt;p&gt;Departments&lt;br&gt;
     ↓&lt;br&gt;
Students&lt;br&gt;
     ↓&lt;br&gt;
Enrollments&lt;br&gt;
     ↓&lt;br&gt;
Courses&lt;/p&gt;

&lt;p&gt;This makes the database cleaner and easier to maintain.&lt;br&gt;
If something about the Data Science department changes, we don't want to update hundreds of student records individually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
Learning databases can feel confusing in the beginning because there are so many new terms to learn at once.&lt;br&gt;
But you don't necessarily have to memorize everything separately.&lt;br&gt;
Once you understand how the pieces fit together, it starts making much more sense.&lt;/p&gt;

&lt;p&gt;For me, the biggest thing was realizing that tables aren't just random collections of data. They're designed to work together.&lt;/p&gt;

&lt;p&gt;So if you're currently learning SQL, don't just memorize JOIN syntax.&lt;/p&gt;

&lt;p&gt;Try creating a small database yourself.&lt;br&gt;
Create a few tables, give them primary and foreign keys, establish relationships, and then write queries to bring the information together.&lt;/p&gt;

&lt;p&gt;That's when these concepts really start to click.&lt;/p&gt;

&lt;p&gt;And trust me, once JOINs finally make sense, SQL becomes a lot less scary.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>data</category>
      <category>database</category>
      <category>learning</category>
    </item>
    <item>
      <title>SQL PROJECT:Build a greenwood academy database with postgresql</title>
      <dc:creator>Miss Analyst</dc:creator>
      <pubDate>Mon, 17 Aug 2026 13:40:39 +0000</pubDate>
      <link>https://dev.to/mwatela_nazi_d1d2cd301ba1/sql-projectbuild-a-greenwood-academy-database-with-postgresql-gh1</link>
      <guid>https://dev.to/mwatela_nazi_d1d2cd301ba1/sql-projectbuild-a-greenwood-academy-database-with-postgresql-gh1</guid>
      <description>&lt;p&gt;&lt;strong&gt;INTRODUCTION&lt;/strong&gt;&lt;br&gt;
For this week's SQL assignment, I was given a practical scenario involving Greenwood Academy, a secondary school in Nairobi. The task was to take on the role of a new database administrator and build a school database from scratch, populate it with information, and then use SQL queries to retrieve and work with the data.&lt;/p&gt;

&lt;p&gt;At first, the assignment looked like a lot because there were several different SQL concepts involved. However, as I worked through it step by step, I realized that each section was connected to the next. I started by creating the database structure, added the required information, and finally used queries to make sense of the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHAT THE PROJECT IS ABOUT&lt;/strong&gt;:&lt;br&gt;
We are required to build the data the database from scratch and start querying it, let's go step by step on how we are going to do that.We will start by&lt;br&gt;
 &lt;strong&gt;1.creating a schema called greenwoods_academy;&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%2Fr4b50uck3pejzsycdsjz.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%2Fr4b50uck3pejzsycdsjz.png" alt=" " width="412" height="56"&gt;&lt;/a&gt;&lt;br&gt;
the schema will act as a blue print to ensure our data is stored, exchanged and validated consistently&lt;br&gt;
&lt;strong&gt;2.Creating tables&lt;/strong&gt;&lt;br&gt;
Tables store information that is going to be used in the query. Tables usually have  keys that are important in building databases. Keys help identify records and where relationships are defined, connect information between different tables examples of the keys are primary and foreign key. In our database we have 3 tables that we are going to create;&lt;br&gt;
&lt;strong&gt;(a)create the students table&lt;/strong&gt;&lt;br&gt;
 This table store the students information. The primary key here is the students_id&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%2Fbbcjp4s0ci19j7cli5pi.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%2Fbbcjp4s0ci19j7cli5pi.png" alt=" " width="403" height="226"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;(b)create the subjects table&lt;/strong&gt;&lt;br&gt;
Here the subjects information is going to be stored. The primary key is subject_id&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%2Fn8m2jw3p7bng8viaq1k3.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%2Fn8m2jw3p7bng8viaq1k3.png" alt=" " width="403" height="226"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;(c)create the exam_results table&lt;/strong&gt;&lt;br&gt;
It contains the exam information. The primary key is result_id&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%2F24ga9a3kns2i207fd1ro.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%2F24ga9a3kns2i207fd1ro.png" alt=" " width="412" height="202"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;3.Altering the tables&lt;/strong&gt;&lt;br&gt;
Databases can be changed to suit the users requirements after they have been created, this is very suitable because real world databases might need some adjustments. The school forgot to add a phone_number column, it also needed to rename a column to credit_hours and delete the phone number column. we will use the &lt;strong&gt;ALTER&lt;/strong&gt; function to make these changes. &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%2Fnhrsq5q4snjfocxbjnx0.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%2Fnhrsq5q4snjfocxbjnx0.png" alt=" " width="424" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.filling the database&lt;/strong&gt;&lt;br&gt;
We will now insert data to the tables we created. Here we use the Data manipulation language. I mainly worked with insert, update and delete. You have to be keen when inserting the data to get the right thing&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%2Fkfh806cqdwj95crz2wmi.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%2Fkfh806cqdwj95crz2wmi.png" alt=" " width="790" height="735"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esther Akinyi moved from Nakuru to Nairobi, we will use update to adjust the query&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%2F3fl8hpvrb0yz7pc8xzf3.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%2F3fl8hpvrb0yz7pc8xzf3.png" alt=" " width="232" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the result_id column we entered 59 instead of 49&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%2F1pkng1djjclp7e51ulyj.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%2F1pkng1djjclp7e51ulyj.png" alt=" " width="229" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Result for result_id 9 was cancelled, we use delete to adjust the query&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%2Fj6ca8h98detbgtwqussd.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%2Fj6ca8h98detbgtwqussd.png" alt=" " width="268" height="42"&gt;&lt;/a&gt;&lt;br&gt;
It is very important we have these operations since data in the real work keeps changing&lt;br&gt;
&lt;strong&gt;5.Querying the data&lt;/strong&gt;&lt;br&gt;
Here we retrieve information from the query and we use the &lt;strong&gt;where&lt;/strong&gt; clause. We will first find all students who are in form 4 and all subjects in the science department.&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%2Fs2qig167bga4tdlm1is4.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%2Fs2qig167bga4tdlm1is4.png" alt=" " width="340" height="142"&gt;&lt;/a&gt;&lt;br&gt;
Now we find all exam results whose marks are greater than or equal to 70 and all females only&lt;br&gt;
! &lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/gha3l7cl646r1fmdsz83.png" rel="noopener noreferrer"&gt;Image description&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Using and, or&lt;/strong&gt;&lt;br&gt;
they are used to combine different conditions. For &lt;strong&gt;and&lt;/strong&gt; all conditions must have been satisfied while &lt;strong&gt;or&lt;/strong&gt; either of the two must have been satisfied.&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%2Fdt3fahh5czdssvvqreth.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%2Fdt3fahh5czdssvvqreth.png" alt=" " width="253" height="184"&gt;&lt;/a&gt;&lt;br&gt;
Queries allow you to  easily search for data rather than doing it manually.&lt;br&gt;
&lt;strong&gt;6.Working with operators&lt;/strong&gt;&lt;br&gt;
The operators we are going to use here are &lt;strong&gt;between, in, not in and like&lt;/strong&gt; Between returns values within a range with the boundaries included example 50  and 80 will be included&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%2Fsrjq5pibpfvpp71fy8ry.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%2Fsrjq5pibpfvpp71fy8ry.png" alt=" " width="598" height="121"&gt;&lt;/a&gt;&lt;br&gt;
In matches any value in a list, not in excludes values in a list while like matches a text pattern&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%2F3elef43q0gqn0pvpl8ec.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%2F3elef43q0gqn0pvpl8ec.png" alt=" " width="789" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7.Using count&lt;/strong&gt;&lt;br&gt;
We use count to get the number of records, that matches your query. In our database we will find the number of students who are in form 3 and those that have marks 70 or above&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%2Fn7pxv9glz7k27myuxcnn.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%2Fn7pxv9glz7k27myuxcnn.png" alt=" " width="426" height="133"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;8.Using case when&lt;/strong&gt;&lt;br&gt;
We use case when to assign labels or description to numbers or values&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%2Fjan1j5d9ya1pwimjtmoj.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%2Fjan1j5d9ya1pwimjtmoj.png" alt=" " width="634" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;what I learnt&lt;/strong&gt;&lt;br&gt;
The biggest thing I learned from this assignment is that SQL is not just about writing individual commands. There is a process involved.&lt;/p&gt;

&lt;p&gt;First, I have to create the structure of the database. Then I insert the data, make corrections when necessary, and finally query the information I need.&lt;/p&gt;

&lt;p&gt;I also got more comfortable with commands such as CREATE, ALTER, INSERT, UPDATE, DELETE, SELECT, WHERE, BETWEEN, IN, LIKE, COUNT(), and CASE WHEN.&lt;/p&gt;

&lt;p&gt;Another important lesson was the importance of being precise. A small mistake in a table name, column name, condition, or value can cause a query to fail or return the wrong information. Working through the assignment helped me become more careful with my SQL syntax.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;final thoughts&lt;/strong&gt;&lt;br&gt;
Overall, this assignment gave me a more practical understanding of how databases work. Instead of only learning SQL commands individually, I got to use them in a situation that resembles something a real school might need.&lt;/p&gt;

&lt;p&gt;Starting with an empty database and gradually building it into something that could store student, subject, and examination information made the different SQL concepts easier to connect.&lt;/p&gt;

&lt;p&gt;The assignment also helped me see how SQL can be used to organize information, correct mistakes, search through large amounts of data, and turn raw data into useful information. Going forward, I feel more confident about using SQL for larger and more realistic database projects.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>HOW EXCEL IS USED IN REAL-WORLD DATA ANALYSIS</title>
      <dc:creator>Miss Analyst</dc:creator>
      <pubDate>Wed, 10 Jun 2026 08:03:27 +0000</pubDate>
      <link>https://dev.to/mwatela_nazi_d1d2cd301ba1/how-excel-is-used-in-real-world-data-analysis-1jop</link>
      <guid>https://dev.to/mwatela_nazi_d1d2cd301ba1/how-excel-is-used-in-real-world-data-analysis-1jop</guid>
      <description>&lt;p&gt;INTRODUCTION&lt;br&gt;
Data is raw facts and figures that have less meaning  to the user therefore we use tools such as excel to organize,analyse and visualize it. Lets dig deep to what excel is&lt;br&gt;
&lt;strong&gt;EXCEL?&lt;/strong&gt;&lt;br&gt;
It is a spreadsheet application that allows users to store data in rows and columns, perform calculations using formulas,create charts and graphs and generates reports&lt;/p&gt;

&lt;p&gt;USES OF EXCELL IN THE REAL WORLD&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data Cleaning and Preparation&lt;/strong&gt;: Data collected from all over including surveys, businesses and research can sometimes be dirty therefore containing duplicate entries, blank cells, spelling mistakes or inconsistent formatting. Excel provides tools such as Remove Duplicates, Find and Replace, Text to Columns and sort and Filter to correct these issues. Clean data ensures that the final analysis is accurate and reliable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;2.&lt;strong&gt;Financial Reporting and Budgeting&lt;/strong&gt;: Organizations and businesses can track income, expenses and profits using spreadsheets. This makes it easier to plan budgets and monitor financial performance without complicated software.&lt;/p&gt;

&lt;p&gt;3.&lt;strong&gt;Business decision-making:&lt;/strong&gt; Companies collect alot of information every day, such as sales figures and customer data. Excel helps organize this information so managers can identify trends and make better decisions about their products or services.&lt;/p&gt;

&lt;h2&gt;
  
  
  EXCEL FEATURES AND FORMULAS I HAVE LEARNED
&lt;/h2&gt;

&lt;p&gt;Excel has several features and formulas that make data analysis easier and more efficient, they include&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.=SUM FUNCTION&lt;/strong&gt;- It is used to add values within a selected range of cells example  =SUM(A1:A10)  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. =AVERAGE FUNCTION&lt;/strong&gt;-It is used to calculate the mean of a group of numbers example =AVERAGE(B1:B10)&lt;br&gt;&lt;br&gt;
It is useful for finding the average score of students monthly income or average customer ratings.&lt;/p&gt;

&lt;p&gt;*&lt;strong&gt;&lt;em&gt;3.IF Function *&lt;/em&gt;-&lt;/strong&gt;The IF function performs logical tests and returns different results depending on whether a condition is true or false&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.Sort and Filter&lt;/strong&gt;-This feature is used to organize data and display only relevant information therefore making data cleaning easier to improve the quality of analysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONCLUSION&lt;/strong&gt;&lt;br&gt;
Learning Excel has changed the way I see data. I no longer view data as just rows of numbers but as valuable information that can answer questions and solve problems when it is properly cleaned and analyzed. Excel has enhanced my understanding of data and it's role in solving real-world problems making it an essential skill in todays data-driven world.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>data</category>
      <category>microsoft</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
