SQL Cheatsheet
Quick reference for SQL syntax covering DDL, DML, SELECT queries, JOINs, aggregate functions, subqueries, window functions, and indexing
69 commands
CREATE TABLECreate a table
CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(100), email VARCHAR(255));DROP TABLEDrop a table
DROP TABLE IF EXISTS users;ALTER TABLE ADDAdd a column to a table
ALTER TABLE users ADD COLUMN age INT;ALTER TABLE DROPDrop a column from a table
ALTER TABLE users DROP COLUMN age;ALTER TABLE MODIFYModify column type
ALTER TABLE users MODIFY COLUMN name VARCHAR(200);ALTER TABLE RENAMERename a table
ALTER TABLE users RENAME TO members;TRUNCATE TABLEFast delete all rows from table
TRUNCATE TABLE logs;CREATE DATABASECreate a database
CREATE DATABASE myapp;DROP DATABASEDrop a database
DROP DATABASE IF EXISTS myapp;CREATE VIEWCreate a view
CREATE VIEW active_users AS SELECT * FROM users WHERE status = 'active';INSERT INTOInsert data
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');INSERT INTO ... SELECTInsert from SELECT result
INSERT INTO archive SELECT * FROM logs WHERE created_at < '2024-01-01';UPDATEUpdate data
UPDATE users SET name = 'Bob' WHERE id = 1;DELETEDelete data
DELETE FROM users WHERE status = 'inactive';UPSERT (MySQL)Insert or update on duplicate (MySQL)
INSERT INTO users (id, name) VALUES (1, 'Alice') ON DUPLICATE KEY UPDATE name = 'Alice';UPSERT (PostgreSQL)Insert or update on conflict (PostgreSQL)
INSERT INTO users (id, name) VALUES (1, 'Alice') ON CONFLICT (id) DO UPDATE SET name = 'Alice';MERGEMerge (upsert operation)
MERGE INTO target USING source ON target.id = source.id WHEN MATCHED THEN UPDATE SET ... WHEN NOT MATCHED THEN INSERT ...;SELECTRetrieve data
SELECT name, email FROM users;SELECT DISTINCTSelect distinct values
SELECT DISTINCT country FROM users;WHEREFilter with conditions
SELECT * FROM users WHERE age >= 18;AND / ORCombine multiple conditions
SELECT * FROM users WHERE age >= 18 AND status = 'active';INCheck if value is in a list
SELECT * FROM users WHERE country IN ('US', 'JP', 'UK');BETWEENGet values within a range
SELECT * FROM orders WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';LIKEPattern matching
SELECT * FROM users WHERE name LIKE 'A%';IS NULL / IS NOT NULLNULL check
SELECT * FROM users WHERE email IS NOT NULL;ORDER BYSort results
SELECT * FROM users ORDER BY created_at DESC;LIMIT / OFFSETLimit number of rows
SELECT * FROM users LIMIT 10 OFFSET 20;CASE WHENConditional expression
SELECT name, CASE WHEN age >= 18 THEN 'Adult' ELSE 'Minor' END AS category FROM users;COALESCEReturn first non-null value
SELECT COALESCE(nickname, name, 'Unknown') FROM users;INNER JOINInner join (matching rows only)
SELECT u.name, o.total FROM users u INNER JOIN orders o ON u.id = o.user_id;LEFT JOINLeft outer join (keep all left rows)
SELECT u.name, o.total FROM users u LEFT JOIN orders o ON u.id = o.user_id;RIGHT JOINRight outer join (keep all right rows)
SELECT u.name, o.total FROM users u RIGHT JOIN orders o ON u.id = o.user_id;FULL OUTER JOINFull outer join (keep all rows)
SELECT u.name, o.total FROM users u FULL OUTER JOIN orders o ON u.id = o.user_id;CROSS JOINCross join (all combinations)
SELECT * FROM colors CROSS JOIN sizes;SELF JOINSelf join (join table to itself)
SELECT e.name, m.name AS manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.id;NATURAL JOINNatural join (auto-join on same columns)
SELECT * FROM orders NATURAL JOIN customers;COUNTCount rows
SELECT COUNT(*) FROM users;SUMCalculate sum
SELECT SUM(amount) FROM orders;AVGCalculate average
SELECT AVG(price) FROM products;MAXGet maximum value
SELECT MAX(salary) FROM employees;MINGet minimum value
SELECT MIN(price) FROM products;GROUP BYGroup and aggregate
SELECT country, COUNT(*) FROM users GROUP BY country;HAVINGFilter after grouping
SELECT country, COUNT(*) AS cnt FROM users GROUP BY country HAVING cnt > 10;GROUP_CONCAT (MySQL)Concatenate values in group
SELECT department, GROUP_CONCAT(name) FROM employees GROUP BY department;STRING_AGG (PostgreSQL)Concatenate values in group
SELECT department, STRING_AGG(name, ', ') FROM employees GROUP BY department;WHERE ... IN (SELECT)Filter by subquery result
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE total > 100);EXISTSCheck if subquery returns rows
SELECT * FROM users u WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);スカラーサブクエリScalar subquery returning single value
SELECT name, (SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS order_count FROM users u;WITH (CTE)Define Common Table Expression
WITH active AS (SELECT * FROM users WHERE status = 'active') SELECT * FROM active WHERE age > 25;WITH RECURSIVEDefine recursive CTE
WITH RECURSIVE tree AS (SELECT id, name, parent_id FROM categories WHERE parent_id IS NULL UNION ALL SELECT c.id, c.name, c.parent_id FROM categories c JOIN tree t ON c.parent_id = t.id) SELECT * FROM tree;UNIONCombine results (remove duplicates)
SELECT name FROM users UNION SELECT name FROM admins;UNION ALLCombine results (keep duplicates)
SELECT name FROM users UNION ALL SELECT name FROM admins;ROW_NUMBER()Assign row numbers
SELECT name, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank FROM employees;RANK()Assign rank (gaps on ties)
SELECT name, RANK() OVER (ORDER BY score DESC) AS rank FROM students;DENSE_RANK()Assign rank (no gaps on ties)
SELECT name, DENSE_RANK() OVER (ORDER BY score DESC) AS rank FROM students;LAG()Get value from previous row
SELECT date, amount, LAG(amount) OVER (ORDER BY date) AS prev_amount FROM sales;LEAD()Get value from next row
SELECT date, amount, LEAD(amount) OVER (ORDER BY date) AS next_amount FROM sales;SUM() OVERCalculate running total
SELECT date, amount, SUM(amount) OVER (ORDER BY date) AS running_total FROM sales;PARTITION BYApply window function within partition
SELECT dept, name, salary, RANK() OVER (PARTITION BY dept ORDER BY salary DESC) FROM employees;NTILE()Divide rows into N equal groups
SELECT name, NTILE(4) OVER (ORDER BY score DESC) AS quartile FROM students;CREATE INDEXCreate an index
CREATE INDEX idx_users_email ON users (email);CREATE UNIQUE INDEXCreate a unique index
CREATE UNIQUE INDEX idx_users_email ON users (email);DROP INDEXDrop an index
DROP INDEX idx_users_email;PRIMARY KEYSet primary key constraint
ALTER TABLE users ADD PRIMARY KEY (id);FOREIGN KEYSet foreign key constraint
ALTER TABLE orders ADD FOREIGN KEY (user_id) REFERENCES users(id);UNIQUESet unique constraint
ALTER TABLE users ADD CONSTRAINT uk_email UNIQUE (email);CHECKSet check constraint
ALTER TABLE users ADD CONSTRAINT chk_age CHECK (age >= 0);NOT NULLSet NOT NULL constraint
ALTER TABLE users MODIFY COLUMN name VARCHAR(100) NOT NULL;DEFAULTSet default value
ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active';