<?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: Gumathi Geo</title>
    <description>The latest articles on DEV Community by Gumathi Geo (@mysticg).</description>
    <link>https://dev.to/mysticg</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%2F3964100%2F9a175a32-93d8-41c8-977f-ec2549558c5f.png</url>
      <title>DEV Community: Gumathi Geo</title>
      <link>https://dev.to/mysticg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mysticg"/>
    <language>en</language>
    <item>
      <title>A quick review of SQL Joins</title>
      <dc:creator>Gumathi Geo</dc:creator>
      <pubDate>Fri, 11 Sep 2026 05:58:22 +0000</pubDate>
      <link>https://dev.to/mysticg/a-quick-review-of-sql-joins-1ic7</link>
      <guid>https://dev.to/mysticg/a-quick-review-of-sql-joins-1ic7</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;SQL Joins, Simply&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Join combines rows from two tables, matched on shared column, usually an id.&lt;/p&gt;

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

&lt;p&gt;customers                  orders&lt;/p&gt;




&lt;p&gt;customer_id | name         order_id | customer_id | item&lt;br&gt;
1           | Amina        101      | 1           | Bag&lt;br&gt;
2           | Brian        102      | 1           | Shoes&lt;br&gt;
3           | Carla        103      | 5           | Hat&lt;/p&gt;

&lt;p&gt;Note: customer_id 5 has no match in customers. Carla has no orders. These gaps show what each join does differently.&lt;/p&gt;

&lt;p&gt;_Inner Join _— only matching rows on both sides.&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT customers.name, orders.item&lt;br&gt;
FROM customers&lt;br&gt;
INNER JOIN orders ON customers.customer_id = orders.customer_id;&lt;/p&gt;

&lt;p&gt;Result: Amina's two orders only. Carla and order 103 drop out, no match.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Left Join&lt;/em&gt; — keeps all rows from left table, matched or not.&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT customers.name, orders.item&lt;br&gt;
FROM customers&lt;br&gt;
LEFT JOIN orders ON customers.customer_id = orders.customer_id;&lt;/p&gt;

&lt;p&gt;Result: Amina's orders plus Carla with NULL item.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Right Join&lt;/em&gt; — keeps all rows from right table, matched or not.&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT customers.name, orders.item&lt;br&gt;
FROM customers&lt;br&gt;
RIGHT JOIN orders ON customers.customer_id = orders.customer_id;&lt;/p&gt;

&lt;p&gt;Result: Amina's orders plus order 103 with NULL name.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Full Join&lt;/em&gt; — keeps all rows from both tables.&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT customers.name, orders.item&lt;br&gt;
FROM customers&lt;br&gt;
FULL JOIN orders ON customers.customer_id = orders.customer_id;&lt;/p&gt;

&lt;p&gt;Result: Amina's orders, Carla with NULL item, order 103 with NULL name. Nothing dropped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick rule
&lt;/h2&gt;

&lt;p&gt;: Inner join = strict match only. Left/right = pick which side to keep fully. Full join = keep everything. Default to inner join unless missing rows matter to your question.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>database</category>
      <category>programming</category>
      <category>sql</category>
    </item>
    <item>
      <title>A DEEP DIVE INTO DDL'S AND DML'S</title>
      <dc:creator>Gumathi Geo</dc:creator>
      <pubDate>Fri, 11 Sep 2026 05:40:55 +0000</pubDate>
      <link>https://dev.to/mysticg/a-deep-dive-into-ddls-and-dmls-4i8j</link>
      <guid>https://dev.to/mysticg/a-deep-dive-into-ddls-and-dmls-4i8j</guid>
      <description>&lt;h2&gt;
  
  
  _ &lt;u&gt;DDL and DML, the basics&lt;/u&gt;_
&lt;/h2&gt;

&lt;p&gt;I keep seeing these two terms thrown around whenever people talk SQL, so here's what I've picked up about them so far.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;u&gt;DDL&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DDL stands for Data Definition Language. Basically, these are the commands that deal with the structure of a database — the tables themselves, not what's sitting inside them. If you're creating a table, changing its columns, or getting rid of it completely, that's DDL.&lt;/p&gt;

&lt;p&gt;Say I'm building a small table to track books at a library:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
CREATE TABLE library.books (&lt;br&gt;
    book_id VARCHAR(20) NOT NULL,&lt;br&gt;
    title VARCHAR(150) NULL,&lt;br&gt;
    author VARCHAR(100) NULL,&lt;br&gt;
    date_added TIMESTAMP NULL&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;That's CREATE — it builds a brand new table with the columns you tell it to have.&lt;/p&gt;

&lt;p&gt;Now say I forgot a column and need to add it later, maybe to track whether a book is checked out:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
ALTER TABLE library.books ADD COLUMN is_checked_out BOOLEAN;&lt;/p&gt;

&lt;p&gt;ALTER changes a table that already exists, instead of building a new one.&lt;/p&gt;

&lt;p&gt;If a table isn't needed anymore, DROP removes it completely — structure and all the data in it, gone:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
DROP TABLE library.books;&lt;/p&gt;

&lt;p&gt;There's also TRUNCATE, which is a bit different from DROP. It empties out every row in the table but keeps the table itself standing, so you can start filling it up again without recreating it:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
TRUNCATE TABLE library.books;&lt;/p&gt;

&lt;p&gt;I mixed up DROP and TRUNCATE for a while when I was starting out — DROP kills the table, TRUNCATE just empties it.&lt;/p&gt;

&lt;p&gt;And then there's RENAME, for when a name just isn't working anymore. Maybe books should really be called catalog:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
ALTER TABLE library.books RENAME TO library.catalog;&lt;/p&gt;

&lt;p&gt;You can rename a single column the same way, like if date_added should really be added_on:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
ALTER TABLE library.catalog RENAME COLUMN date_added TO added_on;&lt;/p&gt;

&lt;p&gt;So that's DDL in a nutshell — it's the commands that shape what your database looks like.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;u&gt;DML&lt;/u&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;DML is Data Manipulation Language, and this is where things get more familiar if you've written any SQL at all. DML doesn't touch the structure of a table — it works with the actual rows and data inside it.&lt;/p&gt;

&lt;p&gt;The one everybody starts with is SELECT, for pulling data out:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT * FROM library.catalog WHERE is_checked_out = TRUE;&lt;/p&gt;

&lt;p&gt;This grabs every column, but only for the rows where a book is currently checked out.&lt;/p&gt;

&lt;p&gt;To put new data in, there's INSERT:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
INSERT INTO library.catalog (book_id, title, author)&lt;br&gt;
VALUES ('BK001', 'The Alchemist', 'Paulo Coelho');&lt;/p&gt;

&lt;p&gt;That adds one new row. Notice I didn't fill in every single column — just the ones I had values for.&lt;/p&gt;

&lt;p&gt;To change something that's already there, UPDATE is the one to reach for. Say BK001 just got checked out:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
UPDATE library.catalog&lt;br&gt;
SET is_checked_out = TRUE&lt;br&gt;
WHERE book_id = 'BK001';&lt;/p&gt;

&lt;p&gt;Without the WHERE clause here, every single row in the table gets updated, not just the one you meant — learned that one the hard way on a test database, thankfully.&lt;/p&gt;

&lt;p&gt;And finally DELETE, for getting rid of rows you don't want anymore:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
DELETE FROM library.catalog WHERE book_id = 'BK001';&lt;/p&gt;

&lt;p&gt;This removes just that one row and it's permanent, so it's worth double-checking the WHERE clause before running it. You can also delete based on other conditions, not just an ID — like clearing out anything added before a certain date:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
DELETE FROM library.catalog WHERE added_on &amp;lt; '2024-01-01';&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ACTUAL DIFFERENCE&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;DDL shapes the container — the tables, the columns, whether something exists at all. DML deals with what's poured into that container — adding, changing, reading, or removing the actual rows. If you ever forget which is which, ask yourself: am I changing the table itself, or just what's inside it? That's basically the whole distinction.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>database</category>
      <category>sql</category>
    </item>
    <item>
      <title>SQL for Beginners: Window Functions vs GROUP BY</title>
      <dc:creator>Gumathi Geo</dc:creator>
      <pubDate>Fri, 11 Sep 2026 05:39:43 +0000</pubDate>
      <link>https://dev.to/mysticg/sql-for-beginners-window-functions-vs-group-by-189h</link>
      <guid>https://dev.to/mysticg/sql-for-beginners-window-functions-vs-group-by-189h</guid>
      <description>&lt;p&gt;&lt;strong&gt;Windows function VS Group by&lt;/strong&gt;&lt;br&gt;
Both &lt;strong&gt;window functions&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;GROUP BY&lt;/code&gt;&lt;/strong&gt; help you summarize data. But they do it in different ways, and mixing them up leads to confusing results.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;- &lt;code&gt;GROUP BY&lt;/code&gt; &lt;strong&gt;squishes&lt;/strong&gt; many rows into one row per group.&lt;/li&gt;
&lt;li&gt;- A window function keeps &lt;strong&gt;every row&lt;/strong&gt;, and just adds an extra column next to it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you see that difference, it's easy to know which one to reach for.&lt;/p&gt;

&lt;p&gt;We'll use one simple table the whole way through, so the examples stay easy to follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;students
---------------------------
name      | class | score
---------------------------
Amina     | A     | 90
Brian     | A     | 70
Carla     | A     | 85
Dennis    | B     | 60
Efrem     | B     | 95
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The simple way
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;GROUP BY&lt;/code&gt; answers a question like: &lt;em&gt;"What's the average score in each class?"&lt;/em&gt; It gives you back &lt;strong&gt;fewer rows&lt;/strong&gt; than you started with — one row per class.&lt;/p&gt;

&lt;p&gt;A window function answers a question like: &lt;em&gt;"How does this student's score compare to their class average?"&lt;/em&gt; It gives you back the &lt;strong&gt;same number of rows&lt;/strong&gt; you started with — one per student — just with something extra calculated for each one.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Want one summary row per group? Use &lt;code&gt;GROUP BY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Want to keep every row, but add a calculation? Use a window function.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example 1: GROUP BY — one row per class
&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;-- One row per class. We lose the individual students.&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;class&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;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_score&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class | average_score
------------------------
A     | 81.6
B     | 77.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we no longer see Amina, Brian, or any individual name. &lt;code&gt;GROUP BY&lt;/code&gt; traded the detail for a summary. That's fine when the summary is all you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 2: A window function — keep every row
&lt;/h2&gt;

&lt;p&gt;Now say you want to see each student's score &lt;strong&gt;next to&lt;/strong&gt; their class average, without losing any 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="c1"&gt;-- Every student stays, plus a new column showing their class average.&lt;/span&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;class&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="k"&gt;AVG&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;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="k"&gt;class&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;class_average&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name    | class | score | class_average
------------------------------------------
Amina   | A     | 90    | 81.6
Brian   | A     | 70    | 81.6
Carla   | A     | 85    | 81.6
Dennis  | B     | 60    | 77.5
Efrem   | B     | 95    | 77.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All five students are still there. &lt;code&gt;PARTITION BY class&lt;/code&gt; just tells SQL: "calculate the average separately for each class," instead of one big average for everyone.&lt;/p&gt;

&lt;p&gt;Think of &lt;code&gt;PARTITION BY&lt;/code&gt; as a &lt;code&gt;GROUP BY&lt;/code&gt; that doesn't delete any rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 3: Ranking students in their class
&lt;/h2&gt;

&lt;p&gt;Window functions are also great for ranking. Say you want to know each student's rank inside their own class:&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="c1"&gt;-- Rank students by score, but restart the ranking for each class.&lt;/span&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;class&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;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;class&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;class_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name    | class | score | class_rank
----------------------------------------
Amina   | A     | 90    | 1
Carla   | A     | 85    | 2
Brian   | A     | 70    | 3
Efrem   | B     | 95    | 1
Dennis  | B     | 60    | 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ORDER BY score DESC&lt;/code&gt; says "rank from highest score to lowest." &lt;code&gt;PARTITION BY class&lt;/code&gt; says "start the ranking over again for each class." That's why both Amina and Efrem get rank 1 — one for class A, one for class B.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 4: Comparing a row to the one before it
&lt;/h2&gt;

&lt;p&gt;Another handy window function is &lt;code&gt;LAG()&lt;/code&gt;. It looks at the previous row so you don't have to join a table to itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scores_by_month
--------------------
month  | score
--------------------
Jan    | 60
Feb    | 70
Mar    | 65
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Show each month's score next to last month's score.&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;score&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;score&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="k"&gt;month&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_month_score&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;scores_by_month&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;month | score | previous_month_score
----------------------------------------
Jan   | 60    | NULL
Feb   | 70    | 60
Mar   | 65    | 70
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;January has &lt;code&gt;NULL&lt;/code&gt; because there's no month before it. Every other row simply grabs the score from the row above it.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use which — quick guide
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you want&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;Just the average/total/count per group&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GROUP BY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Individual rows AND a group calculation together&lt;/td&gt;
&lt;td&gt;Window function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A running total&lt;/td&gt;
&lt;td&gt;Window function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ranking rows within a group&lt;/td&gt;
&lt;td&gt;Window function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comparing a row to the row before or after it&lt;/td&gt;
&lt;td&gt;Window function&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Simple mistakes to watch for
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Trying to filter a window function with &lt;code&gt;WHERE&lt;/code&gt;.&lt;/strong&gt; This won't work:&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="c1"&gt;-- This will cause an error.&lt;/span&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;class_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;class_rank&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt; runs before window functions are calculated, so it doesn't know what &lt;code&gt;class_rank&lt;/code&gt; even is yet. Instead, wrap it in a subquery or CTE first, then filter on the outside:&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&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;class&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="k"&gt;class&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;class_rank&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&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;class_rank&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&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;Forgetting &lt;code&gt;ORDER BY&lt;/code&gt; inside &lt;code&gt;OVER()&lt;/code&gt;.&lt;/strong&gt; Without it, running totals won't build up properly — SQL won't know which order to add rows in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mixing up &lt;code&gt;RANK()&lt;/code&gt; and &lt;code&gt;ROW_NUMBER()&lt;/code&gt;.&lt;/strong&gt; If two students tie for the same score, &lt;code&gt;RANK()&lt;/code&gt; gives them the same number. &lt;code&gt;ROW_NUMBER()&lt;/code&gt; always gives out different numbers, even for ties.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-line takeaway
&lt;/h2&gt;

&lt;p&gt;If you just need a summary, use &lt;code&gt;GROUP BY&lt;/code&gt;. If you need to keep every row &lt;em&gt;and&lt;/em&gt; add a calculation next to it, use a window function.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>database</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>SQL for Beginners: Window Functions vs GROUP BY</title>
      <dc:creator>Gumathi Geo</dc:creator>
      <pubDate>Mon, 07 Sep 2026 21:13:52 +0000</pubDate>
      <link>https://dev.to/mysticg/sql-for-beginners-window-functions-vs-group-by-1pc2</link>
      <guid>https://dev.to/mysticg/sql-for-beginners-window-functions-vs-group-by-1pc2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Windows function VS Group by&lt;/strong&gt;&lt;br&gt;
Both &lt;strong&gt;window functions&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;GROUP BY&lt;/code&gt;&lt;/strong&gt; help you summarize data. But they do it in different ways, and mixing them up leads to confusing results.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;code&gt;GROUP BY&lt;/code&gt; &lt;strong&gt;squishes&lt;/strong&gt; many rows into one row per group.&lt;/li&gt;
&lt;li&gt;-A window function keeps &lt;strong&gt;every row&lt;/strong&gt;, and just adds an extra column next to it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you see that difference, it's easy to know which one to reach for.&lt;/p&gt;

&lt;p&gt;We'll use one simple table the whole way through, so the examples stay easy to follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;students
---------------------------
name      | class | score
---------------------------
Amina     | A     | 90
Brian     | A     | 70
Carla     | A     | 85
Dennis    | B     | 60
Efrem     | B     | 95
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Difference between Windows Functions and Group by
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;GROUP BY&lt;/code&gt; answers a question like: &lt;em&gt;"What's the average score in each class?"&lt;/em&gt; It gives you back &lt;strong&gt;fewer rows&lt;/strong&gt; than you started with — one row per class.&lt;/p&gt;

&lt;p&gt;A window function answers a question like: &lt;em&gt;"How does this student's score compare to their class average?"&lt;/em&gt; It gives you back the &lt;strong&gt;same number of rows&lt;/strong&gt; you started with — one per student — just with something extra calculated for each one.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Want one summary row per group? Use &lt;code&gt;GROUP BY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Want to keep every row, but add a calculation? Use a window function.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Example 1: GROUP BY — one row per class&lt;/strong&gt;&lt;/em&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="c1"&gt;-- One row per class. We lose the individual students.&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;class&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;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_score&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class | average_score
------------------------
A     | 81.6
B     | 77.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we no longer see Amina, Brian, or any individual name. &lt;code&gt;GROUP BY&lt;/code&gt; traded the detail for a summary. That's fine when the summary is all you need.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Example 2: A window function — keep every row&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now say you want to see each student's score &lt;strong&gt;next to&lt;/strong&gt; their class average, without losing any 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="c1"&gt;-- Every student stays, plus a new column showing their class average.&lt;/span&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;class&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="k"&gt;AVG&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;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="k"&gt;class&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;class_average&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name    | class | score | class_average
------------------------------------------
Amina   | A     | 90    | 81.6
Brian   | A     | 70    | 81.6
Carla   | A     | 85    | 81.6
Dennis  | B     | 60    | 77.5
Efrem   | B     | 95    | 77.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All five students are still there. &lt;code&gt;PARTITION BY class&lt;/code&gt; just tells SQL: "calculate the average separately for each class," instead of one big average for everyone.&lt;/p&gt;

&lt;p&gt;Think of &lt;code&gt;PARTITION BY&lt;/code&gt; as a &lt;code&gt;GROUP BY&lt;/code&gt; that doesn't delete any rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Example 3: Ranking students in their class&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Window functions are also great for ranking. Say you want to know each student's rank inside their own class:&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="c1"&gt;-- Rank students by score, but restart the ranking for each class.&lt;/span&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;class&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;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;class&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;class_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name    | class | score | class_rank
----------------------------------------
Amina   | A     | 90    | 1
Carla   | A     | 85    | 2
Brian   | A     | 70    | 3
Efrem   | B     | 95    | 1
Dennis  | B     | 60    | 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ORDER BY score DESC&lt;/code&gt; says "rank from highest score to lowest." &lt;code&gt;PARTITION BY class&lt;/code&gt; says "start the ranking over again for each class." That's why both Amina and Efrem get rank 1 — one for class A, one for class B.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Example 4: Comparing a row to the one before it&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another handy window function is &lt;code&gt;LAG()&lt;/code&gt;. It looks at the previous row so you don't have to join a table to itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scores_by_month
--------------------
month  | score
--------------------
Jan    | 60
Feb    | 70
Mar    | 65
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Show each month's score next to last month's score.&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;score&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;score&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="k"&gt;month&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_month_score&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;scores_by_month&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;month | score | previous_month_score
----------------------------------------
Jan   | 60    | NULL
Feb   | 70    | 60
Mar   | 65    | 70
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;January has &lt;code&gt;NULL&lt;/code&gt; because there's no month before it. Every other row simply grabs the score from the row above it.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use which — quick guide
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you want&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;Just the average/total/count per group&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GROUP BY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Individual rows AND a group calculation together&lt;/td&gt;
&lt;td&gt;Window function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A running total&lt;/td&gt;
&lt;td&gt;Window function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ranking rows within a group&lt;/td&gt;
&lt;td&gt;Window function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comparing a row to the row before or after it&lt;/td&gt;
&lt;td&gt;Window function&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Simple mistakes to watch for
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Trying to filter a window function with &lt;code&gt;WHERE&lt;/code&gt;.&lt;/strong&gt; This won't work:&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="c1"&gt;-- This will cause an error.&lt;/span&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;class_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;class_rank&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt; runs before window functions are calculated, so it doesn't know what &lt;code&gt;class_rank&lt;/code&gt; even is yet. Instead, wrap it in a subquery or CTE first, then filter on the outside:&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&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;class&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="k"&gt;class&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;class_rank&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_rank&lt;/span&gt;
&lt;span class="k"&gt;FROM&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;class_rank&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&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;Forgetting &lt;code&gt;ORDER BY&lt;/code&gt; inside &lt;code&gt;OVER()&lt;/code&gt;.&lt;/strong&gt; Without it, running totals won't build up properly — SQL won't know which order to add rows in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mixing up &lt;code&gt;RANK()&lt;/code&gt; and &lt;code&gt;ROW_NUMBER()&lt;/code&gt;.&lt;/strong&gt; If two students tie for the same score, &lt;code&gt;RANK()&lt;/code&gt; gives them the same number. &lt;code&gt;ROW_NUMBER()&lt;/code&gt; always gives out different numbers, even for ties.&lt;/p&gt;

&lt;h2&gt;
  
  
  CONCLUSION
&lt;/h2&gt;

&lt;p&gt;If you just need a summary, use &lt;code&gt;GROUP BY&lt;/code&gt;. If you need to keep every row &lt;em&gt;and&lt;/em&gt; add a calculation next to it, use a window function.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Understanding Database Relationships: From Relational Models to Star and Snowflake Schemas</title>
      <dc:creator>Gumathi Geo</dc:creator>
      <pubDate>Mon, 29 Jun 2026 13:05:49 +0000</pubDate>
      <link>https://dev.to/mysticg/understanding-database-relationships-from-relational-models-to-star-and-snowflake-schemas-56kd</link>
      <guid>https://dev.to/mysticg/understanding-database-relationships-from-relational-models-to-star-and-snowflake-schemas-56kd</guid>
      <description>&lt;h2&gt;
  
  
  INSIGHTS INTO POWER BI DATA ANALYSIS :&lt;em&gt;FROM DATA TO DECISIONS&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Databases are much more than collections of tables—they're systems designed to organize, connect, and retrieve data efficiently. Whether you're building an e-commerce platform, a banking application, or a business intelligence dashboard, understanding database relationships is essential.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore the different types of relationships used in relational databases before introducing two important data warehousing models: the Star Schema and the Snowflake Schema.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Types of Database Relationships&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;There are three primary relationship types you'll encounter in relational databases.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;One-to-One (1:1)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A One-to-One relationship exists when one record in a table corresponds to exactly one record in another table.&lt;/p&gt;

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

&lt;p&gt;One employee has one company ID card&lt;/p&gt;

&lt;p&gt;This type of relationship is commonly used when separating sensitive or optional information into a different table.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Employee&lt;br&gt;
    │&lt;br&gt;
    │&lt;br&gt;
Company ID&lt;/code&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;One-to-Many (1)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The One-to-Many relationship is the most common relationship found in database systems.&lt;br&gt;
One record in the parent table can relate to multiple records in another table.&lt;/p&gt;

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

&lt;p&gt;One customer can place many orders.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Customer&lt;br&gt;
   │&lt;br&gt;
   ├── Order 1&lt;br&gt;
   ├── Order 2&lt;br&gt;
   └── Order 3&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
This relationship keeps information organized by storing customer details only once while linking multiple orders back to the same customer.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Many-to-Many (M)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A Many-to-Many relationship occurs when multiple records in one table can relate to multiple records in another.&lt;/p&gt;

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

&lt;p&gt;Students enroll in many courses.&lt;/p&gt;

&lt;p&gt;Because relational databases cannot directly represent this relationship, an additional table—often called a junction or bridge table—is introduced.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Students&lt;br&gt;
     │&lt;br&gt;
     │&lt;br&gt;
Enrollments&lt;br&gt;
     │&lt;br&gt;
     │&lt;br&gt;
Courses&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This intermediary table stores the associations between the two entities while preserving data integrity.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding Star Schema&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When working with data warehouses and business intelligence, database design follows a slightly different approach.&lt;/p&gt;

&lt;p&gt;One of the most popular models is the Star Schema.&lt;/p&gt;

&lt;p&gt;A Star Schema consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One central Fact Table&lt;/li&gt;
&lt;li&gt;Multiple surrounding Dimension Tables
The fact table stores measurable business data, while the dimension tables provide descriptive information.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;               Date
                 │
                 │
Product ── Sales Fact ── Customer
                 │
                 │
             Store 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;&lt;strong&gt;Fact Table&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The fact table usually contains:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sales Amount&lt;/li&gt;
&lt;li&gt;Quantity Sold&lt;/li&gt;
&lt;li&gt;Profit&lt;/li&gt;
&lt;li&gt;Revenue&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Dimension Tables&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dimension tables provide context such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Customer&lt;/li&gt;
&lt;li&gt;Product&lt;/li&gt;
&lt;li&gt;Store&lt;/li&gt;
&lt;li&gt;Date&lt;/li&gt;
&lt;li&gt;Employee&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Advantages of a Star Schema&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to understand&lt;/li&gt;
&lt;li&gt;Fast analytical queries&lt;/li&gt;
&lt;li&gt;Excellent for dashboards and reporting&lt;/li&gt;
&lt;li&gt;Fewer joins required&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Some information may be duplicated.&lt;/li&gt;
&lt;li&gt;Uses more storage than highly normalized designs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding Snowflake Schema&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Snowflake Schema is an extension of the Star Schema.&lt;br&gt;
Instead of storing all descriptive information in a single dimension table, each dimension is further normalized into multiple related tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                   Date
                    │
                    │
Product ── Sales Fact ── Customer
    │                   │
Category               city
    │                   │
Department        Country
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the Product dimension is split into additional tables like Category and Department, while the Customer dimension connects to City and Country.&lt;/p&gt;

&lt;p&gt;This branching structure resembles a snowflake, which is where the model gets its name. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Star Schema   vs   Snowflake Schema&lt;/strong&gt;&lt;br&gt;
Feature              &lt;em&gt;Star Schema _           _Snowflake Schema&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Structure              Denormalized                Normalized&lt;/li&gt;
&lt;li&gt;Number of Joins   -     Fewer            -                More&lt;/li&gt;
&lt;li&gt;Query Performance  -        Faster        -         Slightly slower&lt;/li&gt;
&lt;li&gt;Storage Usage             - Higher         -                  Lower&lt;/li&gt;
&lt;li&gt;Complexity               -  Simple          -          More complex&lt;/li&gt;
&lt;li&gt;Maintenance             -   Easier           -       More structured&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;When Should You Use Each?&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Choose a Star Schema when:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building dashboards&lt;/li&gt;
&lt;li&gt;Creating reports&lt;/li&gt;
&lt;li&gt;Prioritizing query performance&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Working with business intelligence tools&lt;br&gt;
&lt;em&gt;Choose a Snowflake Schema when:&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reducing data redundancy is important&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintaining strict data consistency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Managing very large enterprise data warehouses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handling complex dimensional hierarchies&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Understanding relationships is the foundation of relational database design. One-to-One, One-to-Many, and Many-to-Many relationships help organize operational databases efficiently, ensuring consistency and minimizing duplication.&lt;/p&gt;

&lt;p&gt;As organizations grow and begin analyzing large volumes of historical data, designs evolve into dimensional models such as the Star Schema and Snowflake Schema. While both support analytical workloads, they differ in complexity, normalization, and performance trade-offs.&lt;/p&gt;

&lt;p&gt;Mastering these concepts not only improves your database design skills but also prepares you to work with modern data warehouses, reporting systems, and business intelligence platforms.&lt;/p&gt;

&lt;p&gt;Whether you're developing applications or designing enterprise data solutions, understanding how these relationships fit together is a skill every developer and data engineer should have.&lt;/p&gt;

&lt;p&gt;If you enjoyed this article, consider leaving a ❤️ and sharing it with other developers. Happy coding!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>learning</category>
      <category>database</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>How Excel Is Used In Real-World Data Analysis</title>
      <dc:creator>Gumathi Geo</dc:creator>
      <pubDate>Sun, 07 Jun 2026 11:14:01 +0000</pubDate>
      <link>https://dev.to/mysticg/how-excel-is-used-in-real-world-data-analysis-2l51</link>
      <guid>https://dev.to/mysticg/how-excel-is-used-in-real-world-data-analysis-2l51</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;INTRODUCTION&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Ms Excel&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Microsoft Excel is a powerful computer software tool that is used to store, organize and analyze data. Excel is a real world data interactive platform made up of worksheets containing rows and columns in which data entries are made ,formatted and analyzed according to a specific                criteria where they can even be presented in visually appealing forms by use of charts and graphs so that they can meet the user's demands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real world applications of Microsoft excel
&lt;/h3&gt;

&lt;p&gt;Microsoft excel is widely used in most data related disciplines, some of the most reputable career paths and fields mainly use excel for real time data processing and data predictions, some of the tasks excel is used for include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data cleaning and preparation&lt;/strong&gt; :Excel is used in removing duplicates present in data sets ,Text formatting and splitting columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exploratory data analysis&lt;/strong&gt;:Tools such as pivot tables are used to explore data and discover hidden patterns, sorting and filtering features can also be used to pin point specific data entries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Advanced calculations and logical testing&lt;/strong&gt; :Excel can be used to perform complex logic operations such as data merging and logical analysis along side statistical modelling to understand data distribution&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Prominent Features and Formulae&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;During my introductory phase of familiarizing with excel i came across some core functions and formulae used in data operations .the functions and formulae used in data operation are as listed below :&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Math &amp;amp; Trigonometry functions&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
They calculate basic arithmetic values and powers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SUM :Adds all numbers in a range.&lt;/li&gt;
&lt;li&gt;SQRT :Calculates the positive square root of a number.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POWER :Raises a base number to a specified exponent.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Statistical Functions&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
They are used to analyze a data set to find central tendencies and extreme values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AVERAGE :Calculates arithmetic mean of a range.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MEDIAN :Identifies the middle number in a sorted list. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MODE :Finds the most frequently occurring number in a data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MAX :Returns the largest value in a set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MIN :Returns the smallest value in a set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;COUNT :Counts cell containing numbers in a range.&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Conditional Statistical Functions&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
They count or add cells only if they meet a specific criteria&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SUMIF :Adds cells that meet one specific condition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;COUNTIF :Counts cells that meet one specific condition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;COUNTIFS: Counts cells that meet multiple specified conditions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SUMIFS :Adds cells that meet specified multiple conditions&lt;br&gt;
&lt;strong&gt;Personal point of view&lt;/strong&gt;&lt;br&gt;
Microsoft excel is a highly recommendable tool for both data scientists and data analysts as it can both be used to find hidden data insights as well as reviewing and deriving information from past data trends.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;CONCLUSION&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmyvsr05wqf0318147dv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmyvsr05wqf0318147dv.png" alt="MICROSOFT EXCEL" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
 Excel is a definitive key to uncovering deeper insights and maximizing your data potential.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>resources</category>
      <category>career</category>
      <category>analytics</category>
    </item>
  </channel>
</rss>
