Returns exactly one row and one column.
SELECT name FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
Returns multiple rows, used with IN, ANY, ALL.
SELECT name FROM employees
WHERE department_id IN (SELECT id FROM departments WHERE location = 'NYC');
Returns multiple columns (one or more rows).
SELECT * FROM employees
WHERE (department_id, job_id) IN (
SELECT department_id, job_id FROM job_assignments
);
Depends on the outer query — evaluated once per row of the outer query.
SELECT name FROM employees e
WHERE salary > (
SELECT AVG(salary) FROM employees WHERE department_id = e.department_id
);
Used to compute derived data per row.
SELECT name,
(SELECT COUNT(*) FROM tasks WHERE tasks.employee_id = e.id) AS task_count
FROM employees e;
Acts like a temporary table in the FROM.
SELECT department_id, AVG(salary)
FROM (
SELECT * FROM employees WHERE status = 'active'
) AS active_employees
GROUP BY department_id;
Checks if subquery returns any rows.
SELECT name FROM employees e
WHERE EXISTS (
SELECT 1 FROM tasks t WHERE t.employee_id = e.id
);
Used to find rows not matched in a subquery.
SELECT name FROM employees e
WHERE NOT EXISTS (
SELECT 1 FROM tasks t WHERE t.employee_id = e.id
);
Used to filter based on value lists.
SELECT name FROM employees
WHERE department_id IN (
SELECT id FROM departments WHERE location = 'NYC'
);
Used to compare a value against multiple returned values.
SELECT name FROM employees
WHERE salary > ANY (SELECT salary FROM employees WHERE department_id = 10);
Update using values from another table.
UPDATE employees
SET salary = salary * 1.1
WHERE department_id = (
SELECT id FROM departments WHERE name = 'Engineering'
);
Delete records based on a condition from another table.
DELETE FROM employees
WHERE id IN (SELECT employee_id FROM terminated_employees);
Insert data from a subquery result.
INSERT INTO retired_employees (id, name)
SELECT id, name FROM employees
WHERE retirement_date <= CURRENT_DATE;
Rule:
Each column should contain atomic (indivisible) values.
Each record should be unique with a primary key.
There should be no repeating groups or arrays in a single column.
Rule:
Table must be in 1NF.
All non-key attributes must depend on the entire primary key (not just part of it).
Mostly relevant when you have a composite primary key.
Rule:
Table must be in 2NF.
Non-key attributes should not depend on other non-key attributes (i.e., no transitive dependencies).