SQL Query Essentials: From Basic Selection to Complex Joins

Selecitng Data

Basic SELECT Statements

SELECT *
FROM customers
WHERE customer_id = 1
ORDER BY first_name;

Selecting Specific Columns

SELECT 
    first_name, 
    last_name, 
    points, 
    points + 10, 
    points / 10 + 100,
    (points + 10) * 100 AS discount_factor,
    (points + 10) * 100 AS 'discount factor'
FROM customers;

Note: Use quotes when column names contain spaces.

SELECT DISTINCT state
FROM customers;

Filtering with WHERE

SELECT *
FROM customers
WHERE points > 3000;

SELECT *
FROM customers
WHERE state = 'VA';

SELECT *
FROM customers
WHERE state <> 'VA';

SELECT *
FROM customers
WHERE birth_date > '1990-01-01';

Logical Operators: AND, OR, NOT

SELECT *
FROM customers
WHERE birth_date > '1990-01-01' 
    OR (points > 1000 AND state = 'VA');

Operator precedence: AND takes priority over OR.

NOT (birth_date > '1990-01-01' OR points > 1000);
birth_date <= '1990-01-01' AND points <= 1000;

IN Operator

SELECT *
FROM customers
WHERE state IN ('VA', 'FL', 'GA');

SELECT *
FROM customers
WHERE state NOT IN ('VA', 'FL', 'GA');

BETWEEN Operator

SELECT *
FROM customers
WHERE points BETWEEN 1000 AND 3000;

Pattern Matching with LIKE

WHERE last_name LIKE 'b%';    -- starts with b
WHERE last_name LIKE '%b%';  -- contains b
WHERE last_name LIKE '%y';   -- ends with y
WHERE last_name LIKE '___y'; -- four chars ending with y
WHERE last_name LIKE 'b__y'; -- starts with b, ends with y, 2 chars between

Wildcards: % matches any number of characters, _ matches exactly one character.

SELECT *
FROM customers
WHERE address LIKE '%trail%' 
    OR address NOT LIKE '%avenue%';

REGEXP for Advanced Pattern Matching

WHERE last_name REGEXP 'field';      -- contains field anywhere
WHERE last_name REGEXP '^field';     -- starts with field
WHERE last_name REGEXP 'field$';     -- ends with field
WHERE last_name REGEXP 'field|mac';  -- contains either
WHERE last_name REGEXP 'field|mac|rose';
WHERE last_name REGEXP '^field|mac|rose'; -- starts with field OR contains mac OR contains rose
WHERE last_name REGEXP '[gim]e';     -- ge, ie, or me
WHERE last_name REGEXP '[a-h]e';     -- ae through he

Handling NULL Values

WHERE phone IS NULL;
WHERE phone IS NOT NULL;

Sorting Results with ORDER BY

SELECT *
FROM customers
ORDER BY first_name;           -- ascending (default)
ORDER BY first_name DESC;      -- descending
ORDER BY state, first_name;    -- multiple columns
ORDER BY state DESC, first_name;

SELECT birth_date, first_name, last_name, 10 AS points 
FROM customers
ORDER BY 1, 2;  -- refer to column positions

SELECT *, quantity * unit_price AS total_price
FROM order_items
WHERE order_id = 2
ORDER BY total_price DESC;

Limiting Results

LIMIT 3;      -- return first 3 rows
LIMIT 6, 3;   -- skip 6, return rows 7-9

The LIMIT clause must appear last in the query.

Combining Tables with JOINs

Inner JOIN

SELECT *
FROM orders
INNER JOIN customers ON orders.customer_id = customers.customer_id;

When column names appear in multiple tables, qualify them:

SELECT orders.customer_id, first_name
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id;

Table aliases streamline queries:

SELECT order_id, o.customer_id, first_name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;

Cross-Database JOINs

USE sql_store;

SELECT *
FROM order_items oi
JOIN sql_inventory.products p ON oi.product_id = p.product_id;

Self JOIN

SELECT *
FROM employees e
JOIN employees m ON e.reports_to = m.employee_id;

Multiple Table JOINs

SELECT *
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
JOIN order_statuses os ON o.status = os.order_status_id;

Compoiste JOIN Conditions

SELECT *
FROM order_items oi
JOIN order_item_notes oin
    ON oi.order_id = oin.order_id
    AND oi.product_id = oin.product_id;

Implicit JOIN Syntax

SELECT *
FROM orders o, customers c
WHERE o.customer_id = c.customer_id;

OUTER JOINs

Inner joins return only matching rows. Outer joins return all rows from one or both tables.

SELECT *
FROM customers c
LEFT JOIN orders o ON c.customer_id = c.customer_id
ORDER BY c.customer_id;

LEFT JOIN returns all customers regardless of order history. RIGHT JOIN returns all orders.

Multiple Table OUTER JOINs

SELECT *
FROM customers c
LEFT JOIN orders o ON c.customer_id = c.customer_id
LEFT JOIN shippers sh ON o.shipper_id = sh.shipper_id;

Self OUTER JOIN

SELECT *
FROM employees e
LEFT JOIN employees m ON e.reports_to = m.employee_id;

This returns managers in the results even when they have no direct reports.

USING Clause

When join columns share the same name:

-- Instead of:
ON o.customer_id = c.customer_id

-- Use:
USING(customer_id);

Multiple columns:

USING(order_id, product_id);

Natural JOIN

SELECT *
FROM orders o
NATURAL JOIN customers c;

The database engine infers the join condition automatically—use with caution.

CROSS JOIN

Produces a Cartesian product of both tables:

SELECT *
FROM orders o
CROSS JOIN products p;

Generates every possible combination of rows from both tables.

Tags: sql database Query SELECT JOIN

Posted on Mon, 14 Sep 2026 16:04:42 +0000 by marque