<?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: Michael Nocito</title>
    <description>The latest articles on DEV Community by Michael Nocito (@michaelnocito).</description>
    <link>https://dev.to/michaelnocito</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%2F4045753%2F6a1c6ad3-194c-4cee-bcc7-1eb047452b0d.png</url>
      <title>DEV Community: Michael Nocito</title>
      <link>https://dev.to/michaelnocito</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michaelnocito"/>
    <language>en</language>
    <item>
      <title>How to Comment SQL So It Teaches</title>
      <dc:creator>Michael Nocito</dc:creator>
      <pubDate>Fri, 24 Jul 2026 15:13:26 +0000</pubDate>
      <link>https://dev.to/michaelnocito/how-to-comment-sql-so-it-teaches-42ak</link>
      <guid>https://dev.to/michaelnocito/how-to-comment-sql-so-it-teaches-42ak</guid>
      <description>&lt;p&gt;This post gives you a complete format for commenting SQL, one that teaches a reader instead of repeating the code back to them. It was built across three published portfolio projects, including one on a 125,000-row Steam dataset, and it is used word for word in those repositories. The whole thing is here. Copy it, change it, make it yours.&lt;/p&gt;

&lt;p&gt;The format exists because of a specific limit. A comment can only be worth reading if it carries something the code does not already say. &lt;code&gt;-- filter to active customers&lt;/code&gt; next to &lt;code&gt;WHERE status = 'active'&lt;/code&gt; carries nothing. The one thing a reader cannot recover from the code is &lt;em&gt;why anyone asked this question in the first place&lt;/em&gt;, and that is usually the part left out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The one-sentence version.&lt;/strong&gt; Put a boxed &lt;strong&gt;WHY&lt;/strong&gt; header above every query. Follow it with a read-out-loud block that paraphrases each clause in the order the clauses appear. Leave the query itself completely clean. All the teaching lives above the code, never inside it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the usual comments fail
&lt;/h2&gt;

&lt;p&gt;Here is what most people write, and what most AI assistants hand you when you ask for commented SQL:&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;-- Get top rated games with at least 500 reviews&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;Positive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;REAL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&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="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;pct_positive&lt;/span&gt; &lt;span class="c1"&gt;-- calc percentage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;games_raw&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Negative&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;500&lt;/span&gt; &lt;span class="c1"&gt;-- filter small samples&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;pct_positive&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three problems, and they compound:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The comments restate the code.&lt;/strong&gt; "filter small samples" next to a &lt;code&gt;WHERE&lt;/code&gt; clause that visibly filters small samples teaches nobody anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The interesting decision is invisible.&lt;/strong&gt; Why 500 and not 50 or 5,000? Why rank on percentage rather than raw count? Those are the analyst judgments. They are the only part a reader cannot reconstruct, and they are the part left out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The inline comments crowd the code.&lt;/strong&gt; Trailing comments push lines long, break alignment, and make the query harder to read than it would have been with no comments at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The format below inverts all three. The reasoning goes on top, the paraphrase goes on top, and the query stays clean.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: the boxed WHY header
&lt;/h2&gt;

&lt;p&gt;Every query gets a full-width box containing a short step name and a &lt;code&gt;WHY&lt;/code&gt; line. The WHY explains the analytical or business reason the question exists. It does not describe what the SQL does.&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;-- ============================================================&lt;/span&gt;
&lt;span class="c1"&gt;-- STEP 4: Each game's positive review PERCENTAGE (quality)&lt;/span&gt;
&lt;span class="c1"&gt;-- WHY: Raw counts favor popular games; a hidden gem is about how&lt;/span&gt;
&lt;span class="c1"&gt;--      WELL-LOVED a game is, not how many reviewed it. Percentage&lt;/span&gt;
&lt;span class="c1"&gt;--      measures quality independent of size. The 500-review floor&lt;/span&gt;
&lt;span class="c1"&gt;--      removes tiny-sample noise; the tiebreaker ranks more-&lt;/span&gt;
&lt;span class="c1"&gt;--      reviewed games above equally-rated smaller ones.&lt;/span&gt;
&lt;span class="c1"&gt;-- ============================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test for a good WHY: delete the query underneath it. Does the header still tell a reader what problem was being solved and what tradeoff was chosen? If yes, it is doing its job. If it collapses into "this selects some games," rewrite it.&lt;/p&gt;

&lt;p&gt;This is also the part that matters most in a portfolio. Anyone reviewing your work can see that you can write a &lt;code&gt;WHERE&lt;/code&gt; clause. What they are actually trying to find out is whether you know why you wrote that particular one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: the read-out-loud block
&lt;/h2&gt;

&lt;p&gt;Directly under the header, one comment line per SQL clause, in the exact order the clauses appear in the query, each line starting with that clause keyword. A beginner should be able to read the block top to bottom and have it land as a sentence.&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;--SELECT Name, Positive, Negative, and a CALCULATED % positive column:&lt;/span&gt;
&lt;span class="c1"&gt;--FROM the games_raw table&lt;/span&gt;
&lt;span class="c1"&gt;--WHERE the game has at least 500 total reviews&lt;/span&gt;
&lt;span class="c1"&gt;--ORDER BY pct_positive DESC, then Positive DESC (tiebreaker)&lt;/span&gt;
&lt;span class="c1"&gt;--LIMIT the first 25 rows&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two rules make this work, and both are easy to break by accident:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Match the query's clause order exactly.&lt;/strong&gt; If the query goes SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, the block goes in that order too. The reader is learning to map the paraphrase onto the code by position.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paraphrase, do not translate word for word.&lt;/strong&gt; "WHERE the game has at least 500 total reviews" is a paraphrase. "WHERE Positive plus Negative is greater than or equal to 500" is a word-for-word translation. It teaches nothing, because it is the same sentence the code already said.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice the block uses &lt;code&gt;--&lt;/code&gt; with no space. That is deliberate. It visually separates the tight teaching block from the spaced-out box header above it. The two then read as distinct layers rather than one wall of comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: sub-bullets for every calculation
&lt;/h2&gt;

&lt;p&gt;Any function or calculated column gets indented sub-bullets under its &lt;code&gt;--SELECT&lt;/code&gt; line, one per piece, in the order a person reads them:&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;--SELECT Name, Positive, Negative, and a CALCULATED % positive column:&lt;/span&gt;
&lt;span class="c1"&gt;--   Positive / (Positive + Negative) * 100  =  % of reviews that are positive&lt;/span&gt;
&lt;span class="c1"&gt;--   CAST(... AS REAL) = treat as a decimal so division keeps decimals&lt;/span&gt;
&lt;span class="c1"&gt;--   ROUND(..., 1)     = round to 1 decimal place&lt;/span&gt;
&lt;span class="c1"&gt;--   AS pct_positive   = name (alias) the new column&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a nested calculation, explain it inside-out, innermost function first. Take &lt;code&gt;ROUND(100.0 * SUM(CASE WHEN status = 'churned' THEN 1 ELSE 0 END) / COUNT(*), 2)&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="c1"&gt;--SELECT the churn rate as a percentage:&lt;/span&gt;
&lt;span class="c1"&gt;--   CASE WHEN status = 'churned' THEN 1 ELSE 0 END = mark each churned row with a 1&lt;/span&gt;
&lt;span class="c1"&gt;--   SUM(...)        = add the 1s, which counts the churned customers&lt;/span&gt;
&lt;span class="c1"&gt;--   / COUNT(*)      = divide by every customer, giving a fraction&lt;/span&gt;
&lt;span class="c1"&gt;--   100.0 * ...     = turn the fraction into a percentage (the .0 forces decimal math)&lt;/span&gt;
&lt;span class="c1"&gt;--   ROUND(..., 2)   = round to 2 decimal places&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That inside-out order matters. It is the order the database evaluates it and the order a person has to unpack it to understand it. Explaining from the outside in produces a description nobody can follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4: the clean query
&lt;/h2&gt;

&lt;p&gt;The SQL itself carries no comments at all. None. Every explanation lives in the block above.&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="n"&gt;Positive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;REAL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&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="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;pct_positive&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;games_raw&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Negative&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;500&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;pct_positive&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the rule people resist, and it is the one that makes the format work. Once the teaching lives in a fixed place above the query, the query becomes something you can read as code. You can copy it without stripping comments, and hand it to a colleague without apology. The separation is the feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full after
&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;-- ============================================================&lt;/span&gt;
&lt;span class="c1"&gt;-- STEP 4: Each game's positive review PERCENTAGE (quality)&lt;/span&gt;
&lt;span class="c1"&gt;-- WHY: Raw counts favor popular games; a hidden gem is about how&lt;/span&gt;
&lt;span class="c1"&gt;--      WELL-LOVED a game is, not how many reviewed it. Percentage&lt;/span&gt;
&lt;span class="c1"&gt;--      measures quality independent of size. The 500-review floor&lt;/span&gt;
&lt;span class="c1"&gt;--      removes tiny-sample noise; the tiebreaker ranks more-&lt;/span&gt;
&lt;span class="c1"&gt;--      reviewed games above equally-rated smaller ones.&lt;/span&gt;
&lt;span class="c1"&gt;-- ============================================================&lt;/span&gt;
&lt;span class="c1"&gt;--SELECT Name, Positive, Negative, and a CALCULATED % positive column:&lt;/span&gt;
&lt;span class="c1"&gt;--   Positive / (Positive + Negative) * 100  =  % of reviews that are positive&lt;/span&gt;
&lt;span class="c1"&gt;--   CAST(... AS REAL) = treat as a decimal so division keeps decimals&lt;/span&gt;
&lt;span class="c1"&gt;--   ROUND(..., 1)     = round to 1 decimal place&lt;/span&gt;
&lt;span class="c1"&gt;--   AS pct_positive   = name (alias) the new column&lt;/span&gt;
&lt;span class="c1"&gt;--FROM the games_raw table&lt;/span&gt;
&lt;span class="c1"&gt;--WHERE the game has at least 500 total reviews&lt;/span&gt;
&lt;span class="c1"&gt;--ORDER BY pct_positive DESC, then Positive DESC (tiebreaker)&lt;/span&gt;
&lt;span class="c1"&gt;--LIMIT the first 25 rows&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;Positive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;REAL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&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="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;pct_positive&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;games_raw&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Negative&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;500&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;pct_positive&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Positive&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same query, same result set, both versions correct. The difference is what a reader walks away with. The WHY makes it a portfolio piece. The read-out-loud block makes it a lesson. The clean query makes it professional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standing conventions that keep it readable
&lt;/h2&gt;

&lt;p&gt;The four parts are the format. These conventions are what stop a long &lt;code&gt;.sql&lt;/code&gt; file from turning into a wall of repeated explanation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teach a function about three times, then stop.&lt;/strong&gt; The first few times &lt;code&gt;ROUND&lt;/code&gt; or &lt;code&gt;CAST&lt;/code&gt; appears in a file, give it a sub-bullet. After that, drop it. A reader who has seen it three times has it, and re-explaining insults them. This fading is deliberate, and it is the single change that keeps long files from becoming exhausting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep a keyword glossary box at the top of the file.&lt;/strong&gt; Open each &lt;code&gt;.sql&lt;/code&gt; file with a boxed "SQL FUNCTIONS &amp;amp; KEYWORDS USED" list, and add to it as new keywords appear. It gives a reader one place to look, and it lets you fade explanations in the body without stranding anyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Give big-picture sections their own boxes.&lt;/strong&gt; Same box width as the query headers. Use it for the things that are not queries: the data-quality story, how the noise was filtered, scope and limitations, how results were validated. These are what turn a file of queries into a document with an argument.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document the data's defects openly.&lt;/strong&gt; If a column is 6% NULL, if a join match rate is 82%, if the snapshot is a year old, write it into a box rather than leaving it out. Stating limitations is not an admission of weakness. It is most of what separates an analyst from someone who ran a query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep the voice calm and beginner-facing.&lt;/strong&gt; Everyday words. No jargon you have not introduced. Write for the version of you that did not know this yet, because that is who reads it, including future you at 11pm six months from now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this works
&lt;/h2&gt;

&lt;p&gt;The format is not just tidiness. Two well-established findings are doing the work.&lt;/p&gt;

&lt;p&gt;The first is the &lt;strong&gt;self-explanation effect&lt;/strong&gt;. Some learners explain worked examples to themselves as they read. They understand and transfer the material considerably better than learners who just read it (Chi, Bassok, Lewis, Reimann &amp;amp; Glaser, 1989, &lt;em&gt;Cognitive Science&lt;/em&gt; 13(2), 145–182). The read-out-loud block is a self-explanation you can rehearse. When you write it yourself, you are forced to say what each clause does. The gaps in your understanding surface immediately, which is exactly when they are cheapest to fix.&lt;/p&gt;

&lt;p&gt;The second is the &lt;strong&gt;generation effect&lt;/strong&gt;. Material you produce yourself is remembered better than material you merely read (Slamecka &amp;amp; Graf, 1978, &lt;em&gt;Journal of Experimental Psychology: Human Learning and Memory&lt;/em&gt; 4(6), 592–604). This is the argument for writing the block yourself on your own queries rather than only reading other people's. It is also why a good study drill on commented SQL is to hide the query, read only the comment block, and rebuild the SQL from it.&lt;/p&gt;

&lt;p&gt;The WHY header is doing something different and simpler: it stores the decision. Six months later the code still shows what you did, but only the header remembers why you chose 500 rather than 50. That is the piece that is genuinely lost otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it on your own project
&lt;/h2&gt;

&lt;p&gt;Retrofitting a whole project at once is miserable and you will abandon it. Do this instead:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with the headers only.&lt;/strong&gt; Go through your existing &lt;code&gt;.sql&lt;/code&gt; file and add just the boxed WHY above each query. Nothing else. This alone captures the reasoning you will otherwise forget, and it takes an afternoon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add read-out-loud blocks to the three hardest queries.&lt;/strong&gt; Not all of them. The ones with a window function, a nested CASE, or a join you had to think about. Those are where a reader gets lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strip the inline comments as you go.&lt;/strong&gt; Every time you add a block above a query, delete the trailing comments inside it. The query gets shorter and better looking immediately, which is the reward that keeps you going.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add the glossary box last&lt;/strong&gt;, once you can see which keywords actually recur.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are starting a project rather than fixing one, write the WHY header &lt;em&gt;before&lt;/em&gt; you write the query. Committing to why you are asking the question tends to change the question, usually for the better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one habit to keep
&lt;/h2&gt;

&lt;p&gt;If you take nothing else from this, write the WHY header. The clause paraphrase helps a beginner and the clean query helps a reviewer. The WHY is the only part that stores something no one can reconstruct from the code later.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The full version of this guide lives on my site: &lt;a href="https://michaelnocito.github.io/analyst-prep-kit/guides/sql-teaching-comments/" rel="noopener noreferrer"&gt;How to Comment SQL So It Teaches&lt;/a&gt;. It adds a cheat sheet and a side-by-side before and after. It is part of the &lt;a href="https://michaelnocito.github.io/analyst-prep-kit/" rel="noopener noreferrer"&gt;Analyst Prep Kit&lt;/a&gt;, browser-based practice kits for SQL, Excel, Python, Power BI, and Tableau.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>beginners</category>
      <category>database</category>
      <category>career</category>
    </item>
  </channel>
</rss>
