Geek Logbook

Tech sea log book

Common table expressions

Specifies a temporary named result set, known as a common table expression (CTE).

Microsoft Documentation

Although there are some time around us the first time someone asked me about it I was confused: I haven’t know its proper definition until that momento. In fact, the common table expressions where added to the SQL standard in 1999

SQL:1999 added a WITH [RECURSIVE] construct allowing recursive queries, like transitive closure, to be specified in the query language itself; see common table expressions.

Wikipedia SQL:1999

Nowadays are used and well known for a lot of people around the world who works with data. There is a really powerful tool for organizing and simplifying complex queries. Because you can change a complex code to a one simpler.

So, for example. We want to simplifed a database for an online store with two tables:

  • customers – Contains information about customers.
    • Columns: id (customer ID), name (customer name)
  • orders – Contains information about orders made by customers.
    • Columns: order_id (order ID), customer_id (customer ID), order_amount (amount of the order)
-- Customers Table
CREATE TABLE customers (
    id INT PRIMARY KEY,
    name VARCHAR(50)
);

INSERT INTO customers (id, name)
VALUES 
    (1, 'John Doe'),
    (2, 'Jane Smith'),
    (3, 'Bob Johnson');

-- Orders Table
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    order_amount DECIMAL(10, 2)
);

INSERT INTO orders (order_id, customer_id, order_amount)
VALUES
    (101, 1, 50.00),
    (102, 1, 30.00),
    (103, 2, 75.00),
    (104, 2, 20.00),
    (105, 3, 100.00);

You can see he result with this query:

SELECT 
    customers.name,
    (
        SELECT SUM(order_amount) 
        FROM orders 
        WHERE orders.customer_id = customers.id
    ) AS total_sales
FROM 
    customers;

But this is much cleaner:

WITH total_sales_cte AS (
    SELECT 
        customer_id,
        SUM(order_amount) AS total_sales
    FROM 
        orders
    GROUP BY 
        customer_id
)

SELECT 
    customers.name,
    cte.total_sales
FROM 
    customers
JOIN 
    total_sales_cte cte ON customers.id = cte.customer_id;

The example below is much more clear than the previous one. We should avoid the use in the following escenarions:

  • Simple Queries
  • One-Time Use
  • Nested CTEs
Tags:

Leave a Reply

Your email address will not be published. Required fields are marked *.

*
*
You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>