Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Cheat Sheets
  3. SQL
  4. SQL SELECT Queries Cheat Sheet
SQLCheat Sheet

SQL SELECT Queries Cheat Sheet

Quick-reference for SELECT fundamentals: filtering with WHERE, sorting with ORDER BY, limiting results, and conditional expressions. Each section includes copy-ready snippets with inline output comments.

On this page
  1. 1SELECT Basics
  2. 2WHERE Clause
  3. 3BETWEEN, IN, LIKE
  4. 4IS NULL / IS NOT NULL
  5. 5ORDER BY
  6. 6LIMIT and OFFSET
  7. 7DISTINCT
  8. 8Column and Table Aliases
  9. 9CASE WHEN Expression
  10. 10Logical Operators
  11. 11Type Casting
  12. 12Complete Query Example
SELECT BasicsWHERE ClauseBETWEEN, IN, LIKEIS NULL / IS NOT NULLORDER BYLIMIT and OFFSETDISTINCTColumn and Table AliasesCASE WHEN ExpressionLogical OperatorsType CastingComplete Query Example

SELECT Basics

SELECT retrieves columns from one or more tables. Use * for all columns or list specific names.

Select all columns
SELECT *
FROM users;
Select specific columns
SELECT id, name, email
FROM users;
Column aliases
SELECT
  first_name AS name,
  email AS contact
FROM users;

AS is optional — `first_name name` works too — but AS is clearer.

Expressions in SELECT
SELECT
  name,
  price,
  price * 0.9 AS discounted_price
FROM products;

WHERE Clause

WHERE filters rows before they reach GROUP BY, SELECT, or ORDER BY. Only rows where the condition evaluates to TRUE are included.

Comparison operators
SELECT * FROM products WHERE price > 100;
SELECT * FROM products WHERE price <= 50;
SELECT * FROM products WHERE status <> 'archived';

<> is the standard SQL "not equal." Some databases also accept !=.

Combining conditions (AND / OR)
-- AND binds tighter than OR — always parenthesize
SELECT * FROM users
WHERE (role = 'admin' OR role = 'editor')
  AND is_active = true;
NOT
SELECT * FROM users
WHERE NOT is_deleted;

BETWEEN, IN, LIKE

Shorthand operators for range checks, set membership, and pattern matching.

BETWEEN (inclusive on both ends)
SELECT * FROM orders
WHERE total BETWEEN 100 AND 500;
-- equivalent: total >= 100 AND total <= 500

For timestamps, prefer >= start AND < end to avoid off-by-one bugs.

IN (set membership)
SELECT * FROM orders
WHERE status IN ('pending', 'processing', 'shipped');
NOT IN
SELECT * FROM users
WHERE role NOT IN ('banned', 'suspended');

NOT IN returns no rows if the list contains NULL. Use NOT EXISTS instead.

LIKE (pattern matching)
-- % = zero or more characters, _ = exactly one
SELECT * FROM users
WHERE email LIKE '%@gmail.com';

SELECT * FROM products
WHERE sku LIKE 'PRD-____';  -- 4 characters after PRD-
ILIKE (case-insensitive, PostgreSQL)
SELECT * FROM products
WHERE name ILIKE '%phone%';

MySQL LIKE is case-insensitive by default (depends on collation). PostgreSQL requires ILIKE.

IS NULL / IS NOT NULL

NULL comparisons require IS NULL — the = operator never matches NULL.

Check for NULL
-- WRONG: = NULL never matches (returns UNKNOWN)
SELECT * FROM users WHERE deleted_at = NULL;

-- RIGHT: use IS NULL
SELECT * FROM users WHERE deleted_at IS NULL;
SELECT * FROM users WHERE deleted_at IS NOT NULL;
COALESCE (default for NULLs)
SELECT
  name,
  COALESCE(nickname, name) AS display_name
FROM users;
-- Returns nickname if non-NULL, otherwise name

ORDER BY

Sort results by one or more columns. Default direction is ASC (ascending).

Ascending and descending
SELECT * FROM products
ORDER BY price ASC;       -- cheapest first (default)

SELECT * FROM products
ORDER BY price DESC;      -- most expensive first
Multiple sort columns
SELECT * FROM users
ORDER BY last_name ASC, first_name ASC;
NULLS FIRST / NULLS LAST
-- PostgreSQL: control where NULLs appear
SELECT * FROM users
ORDER BY last_login DESC NULLS LAST;

Default NULL position varies by database. PostgreSQL: NULLs sort last in ASC, first in DESC.

Order by expression
SELECT * FROM products
ORDER BY price * quantity DESC;

LIMIT and OFFSET

Restrict how many rows are returned and skip rows for pagination.

LIMIT
-- First 10 rows
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 10;
LIMIT + OFFSET (pagination)
-- Page 3 (rows 21-30)
SELECT * FROM products
ORDER BY id
LIMIT 10 OFFSET 20;

OFFSET-based pagination gets slower on later pages. For large tables, use keyset (cursor) pagination instead.

SQL Server syntax (TOP / FETCH)
-- SQL Server: TOP N
SELECT TOP 10 * FROM products ORDER BY price DESC;

-- Standard SQL (also works in PostgreSQL):
SELECT * FROM products
ORDER BY price DESC
FETCH FIRST 10 ROWS ONLY;

DISTINCT

Remove duplicate rows from the result set.

DISTINCT on one column
SELECT DISTINCT country
FROM users
ORDER BY country;
DISTINCT on multiple columns
-- Unique combinations of country + city
SELECT DISTINCT country, city
FROM users;
DISTINCT ON (PostgreSQL)
-- First row per country (by name)
SELECT DISTINCT ON (country)
  country, city, name
FROM users
ORDER BY country, name;

DISTINCT ON is PostgreSQL-specific. Other databases use ROW_NUMBER() window function.

Column and Table Aliases

Aliases rename columns in output or shorten table references. They exist only for the duration of the query.

Column aliases with AS
SELECT
  COUNT(*) AS total_orders,
  SUM(amount) AS revenue
FROM orders;
Table aliases (short names for joins)
SELECT u.name, o.total
FROM users u
JOIN orders o ON o.user_id = u.id;
Alias scope: cannot use in WHERE
-- WRONG: alias not yet available in WHERE
SELECT price * 0.9 AS sale_price
FROM products
WHERE sale_price < 50;  -- ERROR!

-- RIGHT: repeat the expression
SELECT price * 0.9 AS sale_price
FROM products
WHERE price * 0.9 < 50;

Aliases are resolved in SELECT (step 6 of SQL execution order). WHERE runs at step 2.

CASE WHEN Expression

SQL's if/else. Use CASE in SELECT, WHERE, ORDER BY, or inside aggregate functions.

Simple CASE (value matching)
SELECT name,
  CASE status
    WHEN 'active' THEN 'Active'
    WHEN 'inactive' THEN 'Inactive'
    ELSE 'Unknown'
  END AS status_label
FROM users;
Searched CASE (condition matching)
SELECT name, price,
  CASE
    WHEN price < 10 THEN 'budget'
    WHEN price < 100 THEN 'mid-range'
    ELSE 'premium'
  END AS tier
FROM products;
CASE in ORDER BY
-- Custom sort order
SELECT * FROM tickets
ORDER BY
  CASE priority
    WHEN 'critical' THEN 1
    WHEN 'high' THEN 2
    WHEN 'medium' THEN 3
    ELSE 4
  END;
CASE inside aggregates
SELECT
  COUNT(*) AS total,
  SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) AS paid,
  SUM(CASE WHEN status = 'refunded' THEN amount ELSE 0 END) AS refunded_total
FROM orders;

Logical Operators

AND, OR, and NOT combine conditions. AND binds tighter than OR — always parenthesize mixed expressions.

Precedence trap
-- What you wrote:
SELECT * FROM users
WHERE role = 'admin' OR role = 'editor' AND is_active;
-- What SQL evaluates:
-- role = 'admin' OR (role = 'editor' AND is_active)
-- ALL admins (even inactive) plus active editors!

-- Fix: parenthesize
SELECT * FROM users
WHERE (role = 'admin' OR role = 'editor') AND is_active;
NOT with IN / LIKE / BETWEEN
SELECT * FROM products
WHERE category NOT IN ('deprecated', 'hidden');

SELECT * FROM users
WHERE name NOT LIKE 'test%';

SELECT * FROM orders
WHERE total NOT BETWEEN 0 AND 1;  -- likely bad data

Type Casting

Convert values between types with CAST or the :: shorthand (PostgreSQL).

CAST (standard SQL)
SELECT CAST('2024-01-15' AS DATE);
SELECT CAST(price AS INTEGER) FROM products;
SELECT CAST(42 AS TEXT);
:: shorthand (PostgreSQL)
SELECT '2024-01-15'::date;
SELECT price::int FROM products;
SELECT 42::text;

:: is PostgreSQL-specific. Use CAST for portability across databases.

Complete Query Example

A realistic SELECT combining multiple clauses in the correct order.

Full query with all clauses
SELECT
  category,
  COUNT(*) AS product_count,
  ROUND(AVG(price), 2) AS avg_price,
  CASE
    WHEN AVG(price) > 100 THEN 'premium'
    WHEN AVG(price) > 25 THEN 'mid'
    ELSE 'budget'
  END AS tier
FROM products
WHERE is_active = true
  AND created_at >= '2024-01-01'
GROUP BY category
HAVING COUNT(*) >= 3
ORDER BY avg_price DESC
LIMIT 10;

Clause order: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT.

Learn SQL in Depth
SQL Joins Practice →SQL Aggregation Practice →SQL Subqueries Practice →
Warm-up1 / 2

Can you write this from memory?

Select all orders from the orders table where the status equals 'shipped'.

See Also
Joins →Subqueries →

Start Practicing SQL

Free daily exercises with spaced repetition. No credit card required.

← Back to SQL Syntax Practice
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.