Back to Home
    SQLSQL SQL:2023Beginner

    SQL

    SQL queries, joins, aggregations, subqueries, window functions, and database design patterns.

    10 min read
    sqldatabasequeriespostgres

    Basic Queries

    2 topics

    SELECT

    sql
    -- Basic select
    SELECT * FROM users;
    SELECT id, name, email FROM users;
    
    -- Filter
    SELECT * FROM users WHERE age > 18;
    SELECT * FROM users WHERE name LIKE 'A%';
    SELECT * FROM users WHERE status IN ('active', 'trial');
    SELECT * FROM users WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';
    
    -- Sort & limit
    SELECT * FROM users ORDER BY created_at DESC LIMIT 10;
    SELECT * FROM users ORDER BY name ASC NULLS LAST;
    
    -- Distinct
    SELECT DISTINCT country FROM users;

    💡 Avoid SELECT * in production — it fetches unused data

    ⚡ NULLS LAST/FIRST gives you control over NULL ordering

    INSERT, UPDATE, DELETE

    sql
    -- Insert
    INSERT INTO users (name, email, age) VALUES ('Alice', '[email protected]', 30);
    
    -- Insert multiple rows
    INSERT INTO users (name, email) VALUES
      ('Bob', '[email protected]'),
      ('Carol', '[email protected]');
    
    -- Update
    UPDATE users SET status = 'inactive' WHERE last_login < NOW() - INTERVAL '90 days';
    
    -- Delete
    DELETE FROM users WHERE id = 42;
    
    -- Upsert (PostgreSQL)
    INSERT INTO users (email, name) VALUES ('[email protected]', 'Alice')
    ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name;

    ⚠️ Always include WHERE in UPDATE/DELETE — a missing WHERE modifies all rows

    💡 ON CONFLICT ... DO UPDATE is the PostgreSQL upsert pattern

    Joins

    1 topic

    JOIN Types

    sql
    -- INNER JOIN: rows matching in both tables
    SELECT u.name, o.total
    FROM users u
    INNER JOIN orders o ON u.id = o.user_id;
    
    -- LEFT JOIN: all left rows, NULLs for unmatched right
    SELECT u.name, COUNT(o.id) AS order_count
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    GROUP BY u.id, u.name;
    
    -- Multiple joins
    SELECT u.name, p.name AS product, o.created_at
    FROM orders o
    JOIN users u ON u.id = o.user_id
    JOIN products p ON p.id = o.product_id;

    💡 LEFT JOIN is what you want when you want all rows even without a match

    Aggregation

    2 topics

    GROUP BY & HAVING

    sql
    -- Aggregate functions
    SELECT
      COUNT(*)                AS total,
      COUNT(DISTINCT user_id) AS unique_users,
      SUM(amount)             AS revenue,
      AVG(amount)             AS avg_order,
      MAX(amount)             AS largest,
      MIN(created_at)         AS first_order
    FROM orders
    WHERE status = 'completed';
    
    -- GROUP BY
    SELECT country, COUNT(*) AS users
    FROM users
    GROUP BY country
    HAVING COUNT(*) > 100
    ORDER BY users DESC;

    💡 HAVING filters after grouping; WHERE filters before

    ⚡ COUNT(DISTINCT col) counts unique non-NULL values

    Window Functions

    sql
    -- ROW_NUMBER, RANK
    SELECT
      name,
      salary,
      ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank,
      RANK()       OVER (PARTITION BY dept ORDER BY salary DESC) AS dept_rank
    FROM employees;
    
    -- Running total
    SELECT
      created_at::date AS day,
      SUM(amount) AS daily,
      SUM(SUM(amount)) OVER (ORDER BY created_at::date) AS running_total
    FROM orders
    GROUP BY day;
    
    -- LAG / LEAD
    SELECT date, revenue,
      LAG(revenue) OVER (ORDER BY date) AS prev_day
    FROM daily_revenue;

    ⚡ Window functions don't collapse rows like GROUP BY — you keep all rows

    Related Articles

    Background reading and deeper explanations for this sheet.

    Build an Agentic App with FastAPI and Azure AI Foundry: A Practical Beginner-to-Pro Guide

    Learn how to design, build, and deploy an agentic application using FastAPI and Azure AI Foundry with practical, real-world examples. This guide walks you from architecture and setup to tool-calling, memory, observability, and production deployment patterns.

    keyword overlap

    Memory in AI Agents: Vector DB vs Structured State (and When to Use Both)

    AI agents feel smart only when they can remember the right things at the right time. In this practical guide, you’ll learn the difference between vector database memory and structured state, when each approach shines, and how to combine them in real-world agent workflows. We’ll walk through concrete examples, implementation patterns, and pitfalls to avoid so you can build reliable, context-aware agents.

    keyword overlap

    System Design for 100 Million Requests/Day: Scalable Patterns Made Simple

    Designing for 100 million requests a day sounds intimidating, but it becomes manageable when you break traffic into layers and apply proven patterns. In this guide, you’ll learn the architecture, capacity math, and practical system design patterns—like caching, queue-based load leveling, and CQRS—with easy examples you can reuse.

    keyword overlap

    Building Autonomous Agents Without Overengineering: A Practical Guide for Real-World Teams

    Autonomous agents can automate meaningful work, but many projects fail because teams overbuild too early. This practical guide shows you how to design, ship, and improve useful agents with simple patterns, clear guardrails, and real-world examples—without turning your stack into a science project.

    keyword overlap