<?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: Durgesh Yadav</title>
    <description>The latest articles on DEV Community by Durgesh Yadav (@analyticsdurgesh).</description>
    <link>https://dev.to/analyticsdurgesh</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%2F4141317%2F1b5fb39b-0e66-448a-9497-e215a41f19b0.jpg</url>
      <title>DEV Community: Durgesh Yadav</title>
      <link>https://dev.to/analyticsdurgesh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/analyticsdurgesh"/>
    <language>en</language>
    <item>
      <title>Your Spark Job Has 200 Executors. Why Is Only One of Them Working?</title>
      <dc:creator>Durgesh Yadav</dc:creator>
      <pubDate>Thu, 15 Oct 2026 22:31:31 +0000</pubDate>
      <link>https://dev.to/analyticsdurgesh/your-spark-job-has-200-executors-why-is-only-one-of-them-working-3mj</link>
      <guid>https://dev.to/analyticsdurgesh/your-spark-job-has-200-executors-why-is-only-one-of-them-working-3mj</guid>
      <description>&lt;p&gt;Understanding Data Skew in Apache Spark: The Hidden Reason Behind Slow Data Pipelines&lt;/p&gt;

&lt;p&gt;Imagine you’re running a Spark job to process 2 TB of e-commerce data.&lt;/p&gt;

&lt;p&gt;You have configured a cluster with 200 executors. Your code is correct. Your cluster has enough resources. Most tasks finish within a few minutes.&lt;/p&gt;

&lt;p&gt;But one task keeps running.&lt;/p&gt;

&lt;p&gt;Five minutes pass.&lt;/p&gt;

&lt;p&gt;Ten minutes pass.&lt;/p&gt;

&lt;p&gt;Thirty minutes later, that single task is still running while most of your cluster sits idle.&lt;/p&gt;

&lt;p&gt;You increase the number of executors from 200 to 300.&lt;/p&gt;

&lt;p&gt;Nothing changes.&lt;/p&gt;

&lt;p&gt;You increase the memory.&lt;/p&gt;

&lt;p&gt;Still nothing.&lt;/p&gt;

&lt;p&gt;Eventually, your pipeline finishes, but it takes hours longer than expected.&lt;/p&gt;

&lt;p&gt;What went wrong?&lt;/p&gt;

&lt;p&gt;One possible reason is Data Skew.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fox8p5p03yq9mguimief3.jpeg" 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%2Fox8p5p03yq9mguimief3.jpeg" alt="Illustration: How data skew can cause one Spark task to become a bottleneck while other tasks finish early." width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you work with Apache Spark, understanding this concept can fundamentally change how you debug slow pipelines.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, Understand How Spark Distributes Work&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Apache Spark processes data in parallel by dividing it into partitions.&lt;/p&gt;

&lt;p&gt;Think of a company that needs to process one million customer orders.&lt;/p&gt;

&lt;p&gt;Instead of asking one employee to process every order, the company distributes the work across 100 employees.&lt;/p&gt;

&lt;p&gt;If every employee receives approximately 10,000 orders, the workload is balanced.&lt;/p&gt;

&lt;p&gt;But imagine one employee receives 700,000 orders while the remaining 99 employees share just 300,000.&lt;/p&gt;

&lt;p&gt;Even if 99 employees finish early, the company cannot finish until the overloaded employee completes their work.&lt;/p&gt;

&lt;p&gt;Distributed computing works similarly.&lt;/p&gt;

&lt;p&gt;Spark distributes partitions across tasks, and tasks execute on available executor resources.&lt;/p&gt;

&lt;p&gt;Parallelism helps only when the work is distributed reasonably well.&lt;/p&gt;

&lt;p&gt;Having more executors does not automatically mean your workload is balanced.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What Exactly Is Data Skew?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Data skew occurs when data is distributed unevenly across partitions, causing some tasks to process significantly more data than others.&lt;/p&gt;

&lt;p&gt;Let’s take a simple example.&lt;/p&gt;

&lt;p&gt;Suppose an e-commerce company has 100 million order records.&lt;/p&gt;

&lt;p&gt;The company wants to calculate total sales for each seller.&lt;/p&gt;

&lt;p&gt;A simplified dataset looks like this:&lt;/p&gt;

&lt;p&gt;Seller ID   Number of orders&lt;br&gt;
Seller A    70 million&lt;br&gt;
Seller B    10 million&lt;br&gt;
Seller C    8 million&lt;br&gt;
Other sellers   12 million combined&lt;/p&gt;

&lt;p&gt;Seller A alone accounts for 70% of all orders.&lt;/p&gt;

&lt;p&gt;If Spark performs a shuffle-based aggregation by seller_id, all records for a given seller generally need to be brought together for that aggregation stage.&lt;/p&gt;

&lt;p&gt;The partition responsible for Seller A may receive a much larger workload than partitions handling smaller sellers.&lt;/p&gt;

&lt;p&gt;The result?&lt;/p&gt;

&lt;p&gt;One task processes tens of millions of records while other tasks finish quickly.&lt;/p&gt;

&lt;p&gt;That is the practical impact of data skew.&lt;/p&gt;

&lt;p&gt;Important distinction: A frequent value does not automatically cause a performance problem in every Spark operation. The impact depends on the operation, partitioning strategy, data volume, and execution plan.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Why Adding More Executors Doesn’t Necessarily Help&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is where many engineers make an expensive mistake.&lt;/p&gt;

&lt;p&gt;They see a slow Spark job and immediately increase cluster resources.&lt;/p&gt;

&lt;p&gt;But consider what happens when Spark shuffles data by a key.&lt;/p&gt;

&lt;p&gt;If 70 million records belong to the same seller, simply increasing the number of shuffle partitions does not necessarily distribute that seller’s records across those partitions.&lt;/p&gt;

&lt;p&gt;For a standard aggregation or join, records with the same key may still need to be processed together at a particular stage.&lt;/p&gt;

&lt;p&gt;Adding executors can increase available computing capacity, but it cannot automatically eliminate an algorithmic bottleneck.&lt;/p&gt;

&lt;p&gt;Before scaling your cluster, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are a few keys responsible for most of the records?&lt;/li&gt;
&lt;li&gt;Are some tasks processing much more data than others?&lt;/li&gt;
&lt;li&gt;Is the bottleneck caused by skew, insufficient memory, disk spilling, or something else?&lt;/li&gt;
&lt;li&gt;Which operation introduces the expensive shuffle?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Spark UI is often the best place to begin this investigation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How Do You Detect Data Skew in Production?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When debugging a slow pipeline, I would investigate the following signals.&lt;/p&gt;

&lt;p&gt;A. Task duration&lt;/p&gt;

&lt;p&gt;Compare task execution times within the same stage.&lt;/p&gt;

&lt;p&gt;If most tasks finish in 20 seconds but a few take 15 minutes, investigate why.&lt;/p&gt;

&lt;p&gt;Uneven duration alone does not prove skew, but it is a useful signal.&lt;/p&gt;

&lt;p&gt;B. Shuffle read size&lt;/p&gt;

&lt;p&gt;Inspect how much shuffled data each task reads.&lt;/p&gt;

&lt;p&gt;If a small number of tasks read substantially more data than the rest, skew may be contributing to the bottleneck.&lt;/p&gt;

&lt;p&gt;C. Memory and disk spilling&lt;/p&gt;

&lt;p&gt;Large partitions may create substantial memory pressure. Spark can spill intermediate data to disk, increasing execution time.&lt;/p&gt;

&lt;p&gt;D. The data itself&lt;/p&gt;

&lt;p&gt;Run a frequency analysis on important join and aggregation keys.&lt;/p&gt;

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

&lt;p&gt;SELECT&lt;br&gt;
    seller_id,&lt;br&gt;
    COUNT(*) AS order_count&lt;br&gt;
FROM orders&lt;br&gt;
GROUP BY seller_id&lt;br&gt;
ORDER BY order_count DESC&lt;br&gt;
LIMIT 20;&lt;/p&gt;

&lt;p&gt;This query helps identify unusually frequent seller IDs.&lt;/p&gt;

&lt;p&gt;However, key frequency is only one part of the diagnosis. You should also inspect the physical execution plan and Spark UI to understand how the workload is actually distributed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Four Ways to Handle Data Skew&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is no single solution that works for every workload. The correct approach depends on whether the skew occurs during a join, aggregation, or another shuffle-heavy operation.&lt;/p&gt;

&lt;p&gt;Technique 1: Broadcast Join&lt;/p&gt;

&lt;p&gt;Suppose you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An orders table containing 500 million rows&lt;/li&gt;
&lt;li&gt;A seller dimension table containing only 20,000 rows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the smaller table fits safely within the available memory, a broadcast join can distribute it to the executors processing the larger dataset.&lt;/p&gt;

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

&lt;p&gt;from pyspark.sql.functions import broadcast&lt;br&gt;
result = orders.join(&lt;br&gt;
    broadcast(sellers),&lt;br&gt;
    on="seller_id",&lt;br&gt;
    how="left"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;This can avoid shuffling the large orders dataset for the join.&lt;/p&gt;

&lt;p&gt;But there is an important limitation: broadcasting a table that is too large can create memory pressure or even cause executor failures. Always validate the table’s size and the cluster’s available resources.&lt;/p&gt;

&lt;p&gt;Broadcast joins are especially useful when the join’s smaller side is genuinely small enough to broadcast.&lt;/p&gt;

&lt;p&gt;Technique 2: Adaptive Query Execution (AQE)&lt;/p&gt;

&lt;p&gt;Modern Spark versions support Adaptive Query Execution, which can adjust parts of a physical query plan using runtime statistics.&lt;/p&gt;

&lt;p&gt;For skewed sort-merge joins, Spark can identify certain skewed partitions and split them into smaller pieces, processing them alongside replicated pieces of the other join side.&lt;/p&gt;

&lt;p&gt;A common configuration is:&lt;/p&gt;

&lt;p&gt;spark.conf.set(&lt;br&gt;
    "spark.sql.adaptive.enabled",&lt;br&gt;
    "true"&lt;br&gt;
)&lt;br&gt;
spark.conf.set(&lt;br&gt;
    "spark.sql.adaptive.skewJoin.enabled",&lt;br&gt;
    "true"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;These settings enable AQE and its skew-join optimization.&lt;/p&gt;

&lt;p&gt;The precise behavior depends on the Spark version, thresholds, and query plan. AQE is not a universal fix for every skewed aggregation or every slow task.&lt;/p&gt;

&lt;p&gt;Technique 3: Salting&lt;/p&gt;

&lt;p&gt;Salting is a manual technique that can help when a few keys dominate the workload.&lt;/p&gt;

&lt;p&gt;Suppose Seller A has 70 million orders.&lt;/p&gt;

&lt;p&gt;Instead of processing all of Seller A’s records under one key, we can create multiple temporary keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seller A + Salt 0&lt;/li&gt;
&lt;li&gt;Seller A + Salt 1&lt;/li&gt;
&lt;li&gt;Seller A + Salt 2&lt;/li&gt;
&lt;li&gt;Seller A + Salt 3&lt;/li&gt;
&lt;li&gt;Seller A + Salt 4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates more opportunities for parallel processing.&lt;/p&gt;

&lt;p&gt;For aggregations such as SUM, we can calculate partial totals for each salted key and then combine those totals to obtain the final result.&lt;/p&gt;

&lt;p&gt;For joins, we can salt the skewed side and replicate the corresponding rows from the smaller side across the relevant salt values.&lt;/p&gt;

&lt;p&gt;But salting introduces additional work and complexity. It must be designed carefully to preserve the correctness of the result.&lt;/p&gt;

&lt;p&gt;Technique 4: Revisit the Data Model&lt;/p&gt;

&lt;p&gt;Sometimes the best optimization is not a Spark configuration change.&lt;/p&gt;

&lt;p&gt;Ask why one key owns such a large share of the workload.&lt;/p&gt;

&lt;p&gt;Can the business process generate a more balanced key? Can the aggregation be split into partial and final stages? Can the data be compacted or filtered earlier? Is the join actually necessary at its current grain?&lt;/p&gt;

&lt;p&gt;The best solution may come from changing the computation rather than simply adding hardware.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Common Interview Trap: Does Repartitioning Always Fix Skew?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Consider:&lt;/p&gt;

&lt;p&gt;df.repartition(200, "seller_id")&lt;/p&gt;

&lt;p&gt;This repartitions the data using seller_id, but it does not guarantee an even distribution of records across the resulting partitions.&lt;/p&gt;

&lt;p&gt;If Seller A dominates the dataset, its records can still be concentrated in one partition.&lt;/p&gt;

&lt;p&gt;Increasing the number of partitions does not guarantee that a highly frequent key will be split across them.&lt;/p&gt;

&lt;p&gt;This is why engineers must distinguish between two concepts:&lt;/p&gt;

&lt;p&gt;Partitioning: How data is organized and distributed across partitions.&lt;/p&gt;

&lt;p&gt;Skew: How unevenly the workload or data is distributed across those partitions.&lt;/p&gt;

&lt;p&gt;They are related, but they are not the same thing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What I Would Do During a Production Incident&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a critical Spark pipeline suddenly becomes much slower, I would follow a structured investigation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify the slow stage in the Spark UI.&lt;/li&gt;
&lt;li&gt;Compare task durations, shuffle reads, and spill metrics.&lt;/li&gt;
&lt;li&gt;Check whether a few partitions are disproportionately large.&lt;/li&gt;
&lt;li&gt;Inspect join keys and aggregation keys for highly frequent values.&lt;/li&gt;
&lt;li&gt;Review the physical execution plan and whether AQE is active.&lt;/li&gt;
&lt;li&gt;Test the smallest appropriate optimization, such as a broadcast join, skew-join handling, or a two-stage aggregation.&lt;/li&gt;
&lt;li&gt;Compare the result’s correctness and execution metrics before and after the change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I would not immediately increase the executor count without first identifying the bottleneck.&lt;/p&gt;

&lt;p&gt;A larger cluster can help with insufficient overall capacity, but it may provide little improvement when one skewed task determines the completion time.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Bigger Lesson for Data Engineers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Data Engineering is not just about writing transformations that return the correct output.&lt;/p&gt;

&lt;p&gt;It is about understanding how data moves, where computation happens, how resources are consumed, and why a pipeline behaves differently at production scale.&lt;/p&gt;

&lt;p&gt;Data skew connects several essential skills:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distributed computing&lt;/li&gt;
&lt;li&gt;SQL joins and aggregations&lt;/li&gt;
&lt;li&gt;Spark execution plans&lt;/li&gt;
&lt;li&gt;Shuffle mechanics&lt;/li&gt;
&lt;li&gt;Memory and disk management&lt;/li&gt;
&lt;li&gt;Data modeling&lt;/li&gt;
&lt;li&gt;Production debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you understand these relationships, Spark optimization becomes a process of diagnosing evidence rather than randomly changing configurations.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;If your Spark job is slow, don’t ask only:&lt;/p&gt;

&lt;p&gt;How many executors do I need?&lt;/p&gt;

&lt;p&gt;Ask a more useful question:&lt;/p&gt;

&lt;p&gt;Is my data distributed in a way that allows those executors to work efficiently?&lt;/p&gt;

&lt;p&gt;That single question can lead you toward the real bottleneck.&lt;/p&gt;

&lt;p&gt;At PrepNPlaced, I focus on helping aspiring and working Data Engineers understand concepts through practical scenarios, technical depth, and production-oriented problem-solving.&lt;/p&gt;

&lt;p&gt;I’m Durgesh Yadav, and I believe the goal is not simply to learn tools like Spark, Databricks, or Hadoop. It is to understand why they behave the way they do—and how to make them reliable at scale.&lt;/p&gt;

&lt;p&gt;If you’re learning Data Engineering, save this article and revisit the examples when you next troubleshoot a slow Spark job.&lt;/p&gt;

&lt;p&gt;More learning resources: &lt;a href="https://www.prepnplaced.com/" rel="noopener noreferrer"&gt;https://www.prepnplaced.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dataengineering</category>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>webdev</category>
    </item>
    <item>
      <title>this is something mostly everyone goes through!</title>
      <dc:creator>Durgesh Yadav</dc:creator>
      <pubDate>Fri, 25 Sep 2026 07:12:42 +0000</pubDate>
      <link>https://dev.to/analyticsdurgesh/this-is-something-mostly-everyone-goes-through-19ni</link>
      <guid>https://dev.to/analyticsdurgesh/this-is-something-mostly-everyone-goes-through-19ni</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/analyticsdurgesh/5-sql-patterns-that-run-fine-and-still-return-the-wrong-answer-40ka" class="crayons-story__hidden-navigation-link"&gt;5 SQL patterns that run fine and still return the wrong answer&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/analyticsdurgesh" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F4141317%2F1b5fb39b-0e66-448a-9497-e215a41f19b0.jpg" alt="analyticsdurgesh profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/analyticsdurgesh" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Durgesh Yadav
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Durgesh Yadav
                
                
              
              &lt;div id="story-author-preview-content-4738576" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/analyticsdurgesh" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F4141317%2F1b5fb39b-0e66-448a-9497-e215a41f19b0.jpg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Durgesh Yadav&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/analyticsdurgesh/5-sql-patterns-that-run-fine-and-still-return-the-wrong-answer-40ka" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/analyticsdurgesh/5-sql-patterns-that-run-fine-and-still-return-the-wrong-answer-40ka" id="article-link-4738576"&gt;
          5 SQL patterns that run fine and still return the wrong answer
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dataengineering"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dataengineering&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/sql"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;sql&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/beginners"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;beginners&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/analyticsdurgesh/5-sql-patterns-that-run-fine-and-still-return-the-wrong-answer-40ka" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/analyticsdurgesh/5-sql-patterns-that-run-fine-and-still-return-the-wrong-answer-40ka#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>5 SQL patterns that run fine and still return the wrong answer</title>
      <dc:creator>Durgesh Yadav</dc:creator>
      <pubDate>Fri, 25 Sep 2026 05:40:42 +0000</pubDate>
      <link>https://dev.to/analyticsdurgesh/5-sql-patterns-that-run-fine-and-still-return-the-wrong-answer-40ka</link>
      <guid>https://dev.to/analyticsdurgesh/5-sql-patterns-that-run-fine-and-still-return-the-wrong-answer-40ka</guid>
      <description>&lt;p&gt;A database table is really just a spreadsheet. Rows are records — one row&lt;br&gt;
per customer, one row per order. Columns are the fields — a name, a date,&lt;br&gt;
an amount. SQL is the language you use to ask that spreadsheet questions:&lt;br&gt;
show me these rows, combine these two sheets, add these up.&lt;/p&gt;

&lt;p&gt;The five things below aren't about learning more SQL words. They're about&lt;br&gt;
five specific moments where a question you ask gets answered technically&lt;br&gt;
correctly, but not in the way you meant — and nothing warns you. No error&lt;br&gt;
message. Just a wrong number that looks right.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Asking for "everyone" and getting "only some people"
&lt;/h2&gt;

&lt;p&gt;Say you have a table of customers and a table of orders. You want a list&lt;br&gt;
of every customer, showing their order if they have one, and nothing if&lt;br&gt;
they don't — because you still want to see the customers with no orders.&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT c.customer_id, o.order_id&lt;br&gt;
FROM customers c&lt;br&gt;
LEFT JOIN orders o ON c.customer_id = o.customer_id&lt;br&gt;
WHERE o.order_date &amp;gt;= '2026-01-01';&lt;/p&gt;

&lt;p&gt;The LEFT JOIN part does say "keep everyone from the customers list."&lt;br&gt;
But the WHERE line underneath quietly overrides it. Here's why: a&lt;br&gt;
customer with no order gets a blank (called NULL) where their order date&lt;br&gt;
would be. And "is this blank date after 1 January" doesn't have a yes or&lt;br&gt;
no answer — it's neither true nor false, it's just undefined. SQL treats&lt;br&gt;
undefined the same as no, so that customer gets thrown out.&lt;/p&gt;

&lt;p&gt;You asked for everyone. You got only the people who also happen to have a&lt;br&gt;
recent order. Nothing crashed. Nothing warned you. The list is just&lt;br&gt;
quietly shorter than you think it is.&lt;/p&gt;

&lt;p&gt;The picture makes this easier to see than the sentence does:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc3qoj94sw73gs0qw8uf2.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%2Fc3qoj94sw73gs0qw8uf2.png" alt="How a LEFT JOIN quietly turns into an INNER JOIN" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fix is to move the date condition up into the matching step instead&lt;br&gt;
of the filtering step:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
LEFT JOIN orders o&lt;br&gt;
  ON c.customer_id = o.customer_id&lt;br&gt;
  AND o.order_date &amp;gt;= '2026-01-01'&lt;/p&gt;

&lt;p&gt;Now the date check only decides which order to attach, not whether the&lt;br&gt;
customer gets kept.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A "give me everyone except these people" list that comes back empty
&lt;/h2&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT * FROM customers&lt;br&gt;
WHERE customer_id NOT IN (SELECT customer_id FROM cancelled_orders);&lt;/p&gt;

&lt;p&gt;Plain English: show me every customer who isn't in the cancelled-orders&lt;br&gt;
list. Reasonable ask.&lt;/p&gt;

&lt;p&gt;Here's the trap. If even one row in cancelled_orders has a blank&lt;br&gt;
customer_id — maybe a cancellation that was logged before anyone was&lt;br&gt;
assigned to it — the whole comparison breaks. SQL can't say "is this&lt;br&gt;
customer definitely not equal to a blank," so it refuses to say yes for&lt;br&gt;
anyone at all. The entire result becomes empty, for a reason that has&lt;br&gt;
nothing to do with your actual customers.&lt;/p&gt;

&lt;p&gt;Swap it for asking the question a different way — not "is my ID absent&lt;br&gt;
from that list," but "does a cancelled order exist for me":&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT * FROM customers c&lt;br&gt;
WHERE NOT EXISTS (&lt;br&gt;
  SELECT 1 FROM cancelled_orders x&lt;br&gt;
  WHERE x.customer_id = c.customer_id&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;This version isn't confused by a blank value sitting somewhere else in&lt;br&gt;
the list. If you don't know for certain that a column can never contain a&lt;br&gt;
blank, treat this as the safer way to ask the question.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Two ways of counting that quietly disagree
&lt;/h2&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT COUNT(*) AS all_rows, COUNT(phone_number) AS with_phone&lt;br&gt;
FROM customers;&lt;/p&gt;

&lt;p&gt;Counting sounds like it should only have one right answer. It doesn't.&lt;br&gt;
COUNT(*) counts every row, full stop. COUNT(phone_number) counts only&lt;br&gt;
the rows where that specific field actually has something in it —&lt;br&gt;
blanks don't get counted.&lt;/p&gt;

&lt;p&gt;If those two numbers come back different, that gap is telling you exactly&lt;br&gt;
how many customers have no phone number on file. It's a genuinely useful&lt;br&gt;
one-line check for "how messy is this data" before you build anything&lt;br&gt;
more complicated on top of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Adding things up in order, and getting the order wrong
&lt;/h2&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT&lt;br&gt;
  order_date,&lt;br&gt;
  SUM(daily_revenue) OVER (ORDER BY order_date) AS running_total&lt;br&gt;
FROM daily_sales;&lt;/p&gt;

&lt;p&gt;This is meant to build a running total — day one's number, then day one&lt;br&gt;
plus day two, then day one plus two plus three, and so on. Most of the&lt;br&gt;
time it does exactly that.&lt;/p&gt;

&lt;p&gt;The exception: if two rows share the exact same date, some databases&lt;br&gt;
default to treating tied dates as one combined step rather than adding&lt;br&gt;
them one at a time. Your running total can jump differently than expected&lt;br&gt;
right at the point where a date repeats, and it's easy to miss because&lt;br&gt;
the rest of the total looks completely normal.&lt;/p&gt;

&lt;p&gt;Being explicit fixes it:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
SUM(daily_revenue) OVER (&lt;br&gt;
  ORDER BY order_date&lt;br&gt;
  ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;This spells out "add strictly one row at a time," which removes the&lt;br&gt;
ambiguity about what to do with ties.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. A family tree that's missing the person at the top
&lt;/h2&gt;

&lt;p&gt;sql&lt;br&gt;
SELECT e.employee_name, m.employee_name AS manager_name&lt;br&gt;
FROM employees e&lt;br&gt;
JOIN employees m ON e.manager_id = m.employee_id;&lt;/p&gt;

&lt;p&gt;This is a table joined to itself, to line up each employee with their&lt;br&gt;
manager's name. It works for almost everyone — except whoever has no&lt;br&gt;
manager at all, like the CEO or the founder. That one row has a blank&lt;br&gt;
where the manager should be, and a plain join treats a blank as "doesn't&lt;br&gt;
match," so that person disappears from the results entirely.&lt;/p&gt;

&lt;p&gt;You'll get a org chart that looks complete and is quietly missing exactly&lt;br&gt;
one row — the one at the very top.&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
LEFT JOIN employees m ON e.manager_id = m.employee_id&lt;/p&gt;

&lt;p&gt;Same lesson as the very first pattern: whenever a match can land on a&lt;br&gt;
blank, start with LEFT and only switch to a plain join once you're sure&lt;br&gt;
you want to lose that row on purpose.&lt;/p&gt;

&lt;p&gt;Every one of these has the same shape. Something in the data is blank,&lt;br&gt;
or two rows tie, and the ordinary-sounding question you asked gets&lt;br&gt;
answered in a way that's technically consistent but not what you meant.&lt;br&gt;
None of it shows up as an error. It shows up as a number that's wrong in&lt;br&gt;
a way nobody notices until later.&lt;/p&gt;

&lt;p&gt;More worked examples like these, free to browse with no signup, are at&lt;br&gt;
the &lt;a href="https://www.prepnplaced.com/prepnplaced-notes" rel="noopener noreferrer"&gt;https://www.prepnplaced.com/prepnplaced-notes&lt;/a&gt;.&lt;/p&gt;

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