16/04/2025, 09:23 SQL Interview Cheat Sheet
SQL INTERVIEW CHEAT SHEET
BASIC QUERIES & FILTERING
SELECT Statement
SELECT column1, column2 FROM table_name;
SELECT * FROM table_name;
SELECT DISTINCT column FROM table_name;
WHERE Conditions
SELECT * FROM table
WHERE condition;
Common WHERE Operators
column = value
column > value
column BETWEEN value1 AND value2
column IN (val1, val2, val3)
column LIKE 'pattern%'
column IS NULL
condition1 AND condition2
condition1 OR condition2
NOT condition
Ordering Results
SELECT * FROM table
ORDER BY column1 ASC, column2 DESC;
Limiting Results
-- MySQL/PostgreSQL
SELECT * FROM table LIMIT n;
-- SQL Server
SELECT TOP n * FROM table;
JOINS (FREQUENTLY TESTED)
INNER JOIN
SELECT e.name, d.dept_name
FROM employees e
INNER JOIN departments d
ON e.dept_id = d.id;
Returns only matching rows
LEFT JOIN
SELECT c.name, o.order_date
FROM customers c
file:///Users/davidgladson/Downloads/sql_cheatsheet.html 1/7
16/04/2025, 09:23 SQL Interview Cheat Sheet
LEFT JOIN orders o
ON c.id = o.customer_id;
All rows from left table + matching from right
RIGHT JOIN
SELECT e.name, d.dept_name
FROM employees e
RIGHT JOIN departments d
ON e.dept_id = d.id;
All rows from right table + matching from left
FULL OUTER JOIN
SELECT e.name, d.dept_name
FROM employees e
FULL OUTER JOIN departments d
ON e.dept_id = d.id;
All rows from both tables
SELF JOIN
SELECT e1.name employee, e2.name manager
FROM employees e1
JOIN employees e2
ON e1.manager_id = e2.id;
Join table to itself (hierarchical data)
AGGREGATION & GROUPING
Aggregate Functions
COUNT(column|*)
SUM(column)
AVG(column)
MIN(column)
MAX(column)
GROUP BY
SELECT dept_id, AVG(salary) avg_salary
FROM employees
GROUP BY dept_id;
HAVING (filters groups)
SELECT dept_id, AVG(salary) avg_salary
FROM employees
GROUP BY dept_id
HAVING AVG(salary) > 50000;
WHERE filters rows, HAVING filters groups
SUBQUERIES
WHERE Subquery
file:///Users/davidgladson/Downloads/sql_cheatsheet.html 2/7
16/04/2025, 09:23 SQL Interview Cheat Sheet
SELECT name
FROM employees
WHERE dept_id IN (
SELECT id
FROM departments
WHERE location = 'New York'
);
EXISTS Subquery
SELECT name
FROM departments d
WHERE EXISTS (
SELECT 1
FROM employees e
WHERE e.dept_id = d.id
);
FROM Subquery (derived table)
SELECT dept_name, avg_salary
FROM (
SELECT d.name dept_name,
AVG(e.salary) avg_salary
FROM departments d
JOIN employees e
ON d.id = e.dept_id
GROUP BY d.name
) AS dept_stats;
Correlated Subquery
SELECT e.name, e.salary
FROM employees e
WHERE e.salary > (
SELECT AVG(salary)
FROM employees
WHERE dept_id = e.dept_id
);
References outer query in inner query
WINDOW FUNCTIONS
ROW_NUMBER()
SELECT name, dept_id, salary,
ROW_NUMBER() OVER (
PARTITION BY dept_id
ORDER BY salary DESC
) AS salary_rank
FROM employees;
Unique sequential number
RANK() & DENSE_RANK()
SELECT name, dept_id, salary,
RANK() OVER (
ORDER BY salary DESC
) AS salary_rank,
file:///Users/davidgladson/Downloads/sql_cheatsheet.html 3/7
16/04/2025, 09:23 SQL Interview Cheat Sheet
DENSE_RANK() OVER (
ORDER BY salary DESC
) AS dense_rank
FROM employees;
RANK has gaps, DENSE_RANK has no gaps
LAG() & LEAD()
SELECT date, sales,
LAG(sales) OVER (
ORDER BY date
) AS prev_day_sales,
LEAD(sales) OVER (
ORDER BY date
) AS next_day_sales
FROM daily_sales;
Access previous/next row values
Running Totals
SELECT date, amount,
SUM(amount) OVER (
ORDER BY date
) AS running_total
FROM transactions;
COMMON TABLE EXPRESSIONS (CTE)
Basic CTE
WITH dept_salaries AS (
SELECT dept_id, AVG(salary) avg_salary
FROM employees
GROUP BY dept_id
)
SELECT e.name, ds.avg_salary
FROM employees e
JOIN dept_salaries ds
ON e.dept_id = ds.dept_id;
Recursive CTE (hierarchical data)
WITH RECURSIVE emp_hierarchy AS (
-- Base case
SELECT id, name, manager_id, 1 AS level
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Recursive case
SELECT e.id, e.name, e.manager_id, eh.level + 1
FROM employees e
JOIN emp_hierarchy eh
ON e.manager_id = eh.id
)
SELECT * FROM emp_hierarchy;
file:///Users/davidgladson/Downloads/sql_cheatsheet.html 4/7
16/04/2025, 09:23 SQL Interview Cheat Sheet
COMMON INTERVIEW PROBLEMS
Nth Highest Salary
-- Using dense_rank
SELECT salary
FROM (
SELECT salary,
DENSE_RANK() OVER (
ORDER BY salary DESC
) AS rnk
FROM employees
) ranked
WHERE rnk = N;
Finding Duplicates
SELECT col1, col2, COUNT(*) AS count
FROM table_name
GROUP BY col1, col2
HAVING COUNT(*) > 1;
Running Total
SELECT date, amount,
SUM(amount) OVER (
ORDER BY date
) AS running_total
FROM transactions;
Employees Earning More Than Manager
SELECT e.name
FROM employees e
JOIN employees m
ON e.manager_id = m.id
WHERE e.salary > m.salary;
Ranking With Ties
SELECT name, score,
DENSE_RANK() OVER (
ORDER BY score DESC
) AS rank
FROM scores
ORDER BY rank, name;
DATE FUNCTIONS (By Dialect)
MySQL
DATE(datetime_column)
YEAR(date_column)
MONTH(date_column)
DAY(date_column)
DATEDIFF(date1, date2)
DATE_ADD(date, INTERVAL n DAY|MONTH|YEAR)
DATE_SUB(date, INTERVAL n DAY|MONTH|YEAR)
file:///Users/davidgladson/Downloads/sql_cheatsheet.html 5/7
16/04/2025, 09:23 SQL Interview Cheat Sheet
SQL Server
CAST(datetime_col AS DATE)
YEAR(date_column)
MONTH(date_column)
DAY(date_column)
DATEDIFF(day|month|year, date1, date2)
DATEADD(day|month|year, n, date)
PostgreSQL
date_column::DATE
EXTRACT(YEAR FROM date_column)
EXTRACT(MONTH FROM date_column)
EXTRACT(DAY FROM date_column)
date1 - date2
date + INTERVAL 'n days|months|years'
DATABASE DESIGN CONCEPTS
Keys
-- Primary Key
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100)
);
-- Foreign Key
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id)
REFERENCES customers(id)
);
Normalization Levels
1NF: Each cell contains single value
2NF: Non-key attributes depend on the entire PK
3NF: Attributes depend only on the PK
BCNF: For X → Y, X must be a superkey
Index Types
-- Single column index
CREATE INDEX idx_lastname
ON employees(last_name);
-- Composite index
CREATE INDEX idx_name
ON employees(last_name, first_name);
-- Unique index
CREATE UNIQUE INDEX idx_email
ON employees(email);
file:///Users/davidgladson/Downloads/sql_cheatsheet.html 6/7
16/04/2025, 09:23 SQL Interview Cheat Sheet
PERFORMANCE OPTIMIZATION
Query Optimization
1. Index columns in WHERE, JOIN, ORDER BY
2. Avoid SELECT * (select needed columns)
3. Use JOINs instead of subqueries when possible
4. Avoid LIKE '%pattern%' (can't use indexes)
5. Use EXISTS instead of IN for large tables
6. Use EXPLAIN to analyze query plans
7. Avoid functions on indexed columns
8. Use appropriate data types
9. Minimize sorting operations
Index Usage
-- Good: Index can be used
WHERE indexed_col = value
WHERE indexed_col > value
WHERE indexed_col LIKE 'prefix%'
-- Bad: Index can't be used
WHERE UPPER(indexed_col) = 'VALUE'
WHERE indexed_col + 5 > 100
WHERE indexed_col LIKE '%suffix'
Execution Plan Analysis
-- PostgreSQL/MySQL
EXPLAIN SELECT * FROM table;
EXPLAIN ANALYZE SELECT * FROM table;
-- SQL Server
SET SHOWPLAN_ALL ON;
GO
SELECT * FROM table;
file:///Users/davidgladson/Downloads/sql_cheatsheet.html 7/7