---
title: "SQL Execution Order"
description: "SQL queries perform a 3-step operation to filter data..."
canonical_url: "https://otabek.io/blogs/sql-execution-order"
md_url: "https://otabek.io/blogs/sql-execution-order.md"
language: "en"
last_updated: "2024-04-10"
tags: ["Database"]
---

# SQL Execution Order

![SQL execution order](https://telegra.ph/file/30b6f141ebd357228fa99.jpg)

SQL queries perform a three-step operation to filter data:

1. **Row filtering** – This step triggers the `FROM`, `WHERE`, `GROUP BY`, and `HAVING` clauses.
2. **Column filtering** – Columns are usually filtered with the `SELECT` statement.
3. **Row filtering** – The `DISTINCT`, `ORDER BY`, and `LIMIT` clauses are executed.

Yes, you read that correctly: row filtering happens twice. This occurs if your SQL query demands it or if clauses like `DISTINCT`, `ORDER BY`, `LIMIT`, and others are present in the query. Let’s write a query and analyze how this works:

```sql-run
-- CREATE Table and INSERT data [DO NOT EDIT IF YOU RUN THIS CODE]
CREATE TABLE student ( id INTEGER PRIMARY KEY AUTOINCREMENT, full_name TEXT NOT NULL, university TEXT, gpa REAL CHECK (gpa >= 0.0 AND gpa <= 4.0)); INSERT INTO student (full_name, university, gpa) VALUES ('Alice Johnson', 'Harvard University', 3.85), ('Bob Smith', 'MIT', 2.95), ('Clara Lee', 'Stanford University', 3.40), ('Daniel Kim', 'UC Berkeley', 3.00), ('Eva Green', 'Princeton University', 3.92);

-- SELECT from table
SELECT id, full_name, university, gpa FROM student
WHERE gpa > 3.00 ORDER BY full_name;
```

### FROM, WHERE Execution

![WHERE, FROM](https://telegra.ph/file/74c75a6e0ba0b9384f54b.gif)

First, the `FROM` and `WHERE` clauses are executed. But why? Imagine you’re asked to bring a **sanomara** (a specific product). What’s the first thing you’d ask? At the very least, you’d ask **"From which store?"** This is similar to how SQL works. It first runs the `FROM` and `WHERE` clauses to filter the rows. It selects users whose GPA is greater than 3.00 from the student table. This selection is made through some kind of loop mechanism where each row is filtered. If the GPA is greater than 3.00, the row is selected; if not, it moves on to the next one.

### GROUP BY, HAVING Execution

![Grouping](https://telegra.ph/file/721e06d80ef6953ae24bf.gif)

After selecting students with a GPA greater than 3.00, the loop finishes. If you’ve requested data to be grouped, the `GROUP BY` clause will be triggered. If you need to apply additional conditions to the grouped data, you’ll use `HAVING` (not `WHERE`). This is because `WHERE` operates before grouping. After the data is grouped, you’ll need to use the `HAVING` clause to filter, delete, or perform other operations on the grouped data.

### SELECT Execution

![Select](https://telegra.ph/file/0ed4ed6d8d394297eefbd.gif)

The main task of `SELECT` is to return the columns you need. In other words, whatever columns you specify in the `SELECT` statement are what will be shown. If you’re wondering why it’s bad to use `SELECT * FROM ...`, you can read more about it in [this article](select-is-bad).

### ORDER BY, LIMIT Execution

Now that we’ve identified the columns, tables, and rows we want, it’s time to sort them. If you use `ORDER BY`, the query will sort the selected elements by the specified column. If you’ve also applied a `LIMIT`, after sorting, it will return only the number of rows you’ve specified.

As you can see, the speed of an SQL query depends on its various stages, and knowing when to use specific **clauses** is crucial to optimizing performance. Understanding these operations and practicing with them will help you become more efficient. Keep learning and continue following us!

**Telegram**: [@otabekswe](https://t.me/otabekswe)

---

```quiz
{
  "quiz": {
    "id": "sql-execution-quiz",
    "title": "SQL Execution Order Quiz",
    "description": "Test your understanding of how SQL queries execute",
    "questions": [
      {
        "id": "q1",
        "type": "drag-drop",
        "question": "Arrange the SQL clauses in their execution order:",
        "items": [
          { "id": "from", "content": "FROM" },
          { "id": "where", "content": "WHERE" },
          { "id": "groupby", "content": "GROUP BY" },
          { "id": "having", "content": "HAVING" },
          { "id": "select", "content": "SELECT" },
          { "id": "orderby", "content": "ORDER BY" }
        ]
      },
      {
        "id": "q2",
        "type": "single-choice",
        "question": "Which clause is executed first in an SQL query?",
        "options": [
          { "id": "a", "text": "SELECT", "description": "SELECT comes later. FROM is executed first to identify the table." },
          { "id": "b", "text": "FROM", "description": "" },
          { "id": "c", "text": "WHERE", "description": "WHERE comes after FROM." },
          { "id": "d", "text": "ORDER BY", "description": "ORDER BY is one of the last clauses to execute." }
        ]
      },
      {
        "id": "q3",
        "type": "single-choice",
        "question": "Why do we use HAVING instead of WHERE for grouped data?",
        "options": [
          { "id": "a", "text": "WHERE executes before GROUP BY, HAVING executes after", "description": "" },
          { "id": "b", "text": "HAVING is faster", "description": "It's not about speed - HAVING works on grouped data." },
          { "id": "c", "text": "WHERE doesn't work in SQL", "description": "WHERE works fine, but for grouped data you need HAVING." },
          { "id": "d", "text": "They are the same thing", "description": "WHERE filters before grouping, HAVING filters after." }
        ]
      },
      {
        "id": "q4",
        "type": "single-choice",
        "question": "How many times does row filtering happen in SQL?",
        "options": [
          { "id": "a", "text": "Once", "description": "Row filtering happens twice - before and after column selection." },
          { "id": "b", "text": "Twice", "description": "" },
          { "id": "c", "text": "Three times", "description": "Row filtering happens twice in the SQL execution process." },
          { "id": "d", "text": "Never", "description": "Row filtering is a key part of SQL execution." }
        ]
      },
      {
        "id": "q5",
        "type": "single-choice",
        "question": "When is LIMIT applied in the execution order?",
        "options": [
          { "id": "a", "text": "First, before everything else", "description": "LIMIT is applied near the end, after sorting." },
          { "id": "b", "text": "After ORDER BY", "description": "" },
          { "id": "c", "text": "Before SELECT", "description": "LIMIT comes after SELECT and ORDER BY." },
          { "id": "d", "text": "At the same time as FROM", "description": "LIMIT is one of the last operations." }
        ]
      },
      {
        "id": "q6",
        "type": "single-choice",
        "question": "What is the main purpose of the SELECT clause?",
        "options": [
          { "id": "a", "text": "To filter rows", "description": "WHERE filters rows. SELECT chooses columns." },
          { "id": "b", "text": "To return the columns you need", "description": "" },
          { "id": "c", "text": "To sort data", "description": "ORDER BY sorts data. SELECT chooses columns." },
          { "id": "d", "text": "To join tables", "description": "JOIN handles table joining. SELECT chooses columns." }
        ]
      }
    ]
  },
  "answers": {
    "q1": { "correctOrder": ["from", "where", "groupby", "having", "select", "orderby"] },
    "q2": { "correctOptionIds": ["b"] },
    "q3": { "correctOptionIds": ["a"] },
    "q4": { "correctOptionIds": ["b"] },
    "q5": { "correctOptionIds": ["b"] },
    "q6": { "correctOptionIds": ["b"] }
  }
}
```


## Sitemap

See the full [Markdown sitemap](/sitemap.md) for all pages.
