SQL & Database — 17 Topics · MySQL

SQL from Basics to Advanced.

Complete SQL reference — database design, queries, joins, window functions, indexes, normalization, and optimization. 40+ interview questions tagged for FAANG and startups. Free.

MySQL syntax Window functions covered JOIN visuals included Normalization guide
17TopicsBasics to advanced
40+Interview QsFAANG & Startup
5JOIN TypesWith visual guide
3NFNormalization1NF → 2NF → 3NF
+MongoDBNoSQLSQL vs NoSQL guide
01

What is a Database?

A database is a structured collection of related data. In MySQL, a database holds one or more tables — think of it as a folder, where each table is a file inside it.

AnalogyDatabaseTableRow
File SystemFolderFileLine in the file
ExcelWorkbookSheetExcel row
Real worldCompany recordsDepartment listOne employee
Create & Use Database
SQL
CREATE DATABASE techforge_db;
USE techforge_db;
SHOW DATABASES;   -- List all databases
DROP DATABASE techforge_db;  --  Permanent!
After creating the database, use USE database_name; or set it as default schema in your SQL client before running table queries.
02

MySQL Data Types

Data TypeDescriptionExampleInterview Note
INTWhole numbersage INTUse BIGINT for IDs at scale
VARCHAR(n)Variable-length string (up to n chars)name VARCHAR(100)Prefer over CHAR for varying lengths
TEXTLong text (65,535 chars)bio TEXTCannot be indexed directly
DECIMAL(p,s)Exact numeric (p digits, s decimal)price DECIMAL(10,2)Use for money — never FLOAT
DATEDate only (YYYY-MM-DD)dob DATEDATETIME includes time component
TIMESTAMPDate + time, auto-sets to nowcreated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMPStored in UTC
BOOLEANTRUE / FALSE (stored as 1/0)is_active BOOLEAN DEFAULT TRUEAlias for TINYINT(1)
ENUMOne value from a defined setgender ENUM('Male','Female','Other')Validates at DB level
Interview tip: FLOAT/DOUBLE store approximate values. Always use DECIMAL for financial data to avoid rounding errors.
03

Constraints

Constraints enforce rules on column data — they protect data integrity at the database level, not just the application level.

ConstraintPurposeExample
PRIMARY KEYUniquely identifies each row — NOT NULL + UNIQUEid INT PRIMARY KEY
AUTO_INCREMENTAuto-generates sequential integersid INT AUTO_INCREMENT
NOT NULLColumn must always have a valuename VARCHAR(100) NOT NULL
UNIQUEAll values must be distinct (allows NULL)email VARCHAR(100) UNIQUE
DEFAULTUses this value if none providedis_active BOOLEAN DEFAULT TRUE
CHECKValues must satisfy a conditionCHECK (salary > 0)
FOREIGN KEYReferences a primary key in another tableFOREIGN KEY(user_id) REFERENCES users(id)
PRIMARY KEY vs UNIQUE: PRIMARY KEY = NOT NULL + UNIQUE, one per table. UNIQUE allows NULL values and a table can have multiple UNIQUE constraints.
04

Create Table

SQL
CREATE TABLE users (
    id            INT AUTO_INCREMENT PRIMARY KEY,
    name          VARCHAR(100) NOT NULL,
    email         VARCHAR(100) UNIQUE NOT NULL,
    gender        ENUM('Male', 'Female', 'Other'),
    salary        DECIMAL(10,2) DEFAULT 0,
    date_of_birth DATE,
    is_active     BOOLEAN DEFAULT TRUE,
    created_at    TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Verify structure
DESCRIBE users;

-- Remove table entirely (irreversible)
DROP TABLE IF EXISTS users;
05

Alter Table

SQL
-- Add a column
ALTER TABLE users ADD COLUMN phone VARCHAR(15);

-- Drop a column
ALTER TABLE users DROP COLUMN phone;

-- Modify column type
ALTER TABLE users MODIFY COLUMN name VARCHAR(150) NOT NULL;

-- Rename column (MySQL 8.0+)
ALTER TABLE users RENAME COLUMN name TO full_name;

-- Rename table
RENAME TABLE users TO members;
06

Insert Data

Best practice: Always specify column names explicitly. It makes inserts resilient to future schema changes and easier to read.
SQL
-- Single row
INSERT INTO users (name, email, gender, salary, date_of_birth)
VALUES ('Alice', 'alice@example.com', 'Female', 85000, '1995-04-12');

-- Multiple rows at once (more efficient)
INSERT INTO users (name, email, gender, salary, date_of_birth)
VALUES
    ('Bob',     'bob@example.com',     'Male',   72000, '1990-11-23'),
    ('Charlie', 'charlie@example.com', 'Other',  91000, '1988-02-17'),
    ('Divya',   'divya@example.com',   'Female', 67000, '2000-08-09');
07

SELECT Query

SQL
-- Basic SELECT
SELECT * FROM users;
SELECT name, email, salary FROM users;

-- WHERE with operators
SELECT * FROM users WHERE gender = 'Female';
SELECT * FROM users WHERE salary BETWEEN 60000 AND 90000;
SELECT * FROM users WHERE name LIKE 'A%';   -- starts with A
SELECT * FROM users WHERE email IS NOT NULL;

-- AND / OR / NOT
SELECT * FROM users WHERE salary > 70000 AND gender = 'Male';
SELECT * FROM users WHERE department IN ('Eng', 'Design');

-- ORDER and LIMIT
SELECT * FROM users ORDER BY salary DESC LIMIT 10;
SELECT * FROM users ORDER BY name ASC LIMIT 5 OFFSET 10; -- pagination

-- Aliases
SELECT name AS full_name, salary * 12 AS annual_salary FROM users;
08

UPDATE & DELETE

SQL
-- UPDATE specific rows
UPDATE users SET salary = 95000 WHERE id = 1;
UPDATE users SET salary = salary * 1.10 WHERE gender = 'Female'; -- 10% raise

-- DELETE specific rows
DELETE FROM users WHERE id = 3;
DELETE FROM users WHERE is_active = FALSE;

-- TRUNCATE: delete all rows, keep table structure (faster than DELETE)
TRUNCATE TABLE users;
Always use WHERE with UPDATE and DELETE unless you intentionally want to modify every row. Run a SELECT with the same WHERE first to verify which rows are affected.
09

SQL Functions

Aggregate Functions
SQL
SELECT COUNT(*)                    AS total_users    FROM users;
SELECT COUNT(DISTINCT department)  AS dept_count      FROM users;
SELECT MIN(salary), MAX(salary)    AS max_sal        FROM users;
SELECT SUM(salary)                  AS total_payroll  FROM users;
SELECT ROUND(AVG(salary), 2)        AS avg_salary     FROM users;
String & Date Functions
SQL
-- String functions
SELECT UPPER(name), LOWER(email), LENGTH(name) FROM users;
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
SELECT SUBSTRING(email, 1, INSTR(email, '@') - 1) AS username FROM users;

-- Date functions
SELECT YEAR(date_of_birth), MONTH(date_of_birth) FROM users;
SELECT DATEDIFF(NOW(), date_of_birth) / 365 AS age FROM users;
SELECT DATE_FORMAT(created_at, '%Y-%m') AS month FROM users;
10

Window Functions

Window functions perform calculations across rows related to the current row — without collapsing them into groups like GROUP BY does. They're one of the most-tested advanced SQL topics at FAANG companies.

COMMON WINDOW FUNCTIONS
ROW_NUMBER()RANK()DENSE_RANK() LAG()LEAD()NTILE() SUM() OVERAVG() OVERFIRST_VALUE()
SQL
-- ROW_NUMBER: unique rank per partition
SELECT name, department, salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num
FROM users;

-- RANK vs DENSE_RANK: ties behave differently
-- RANK skips numbers after ties; DENSE_RANK does not
SELECT name, salary,
    RANK()       OVER (ORDER BY salary DESC) AS rank_val,
    DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank_val
FROM users;

-- LAG/LEAD: compare current row with previous/next
SELECT name, salary,
    LAG(salary)  OVER (ORDER BY salary) AS prev_salary,
    LEAD(salary) OVER (ORDER BY salary) AS next_salary
FROM users;

-- Running total
SELECT name, salary,
    SUM(salary) OVER (ORDER BY id ROWS UNBOUNDED PRECEDING) AS running_total
FROM users;
Key difference: GROUP BY collapses rows into one per group. Window functions keep all rows and add a calculated column alongside them.
11

Transactions & ACID

A transaction is a sequence of SQL statements treated as a single unit — either all succeed or all fail (atomicity).

ACID PropertyMeaning
AtomicityAll operations succeed or all are rolled back
ConsistencyDB moves from one valid state to another
IsolationConcurrent transactions don't interfere
DurabilityCommitted data persists even after crashes
SQL
START TRANSACTION;

UPDATE accounts SET balance = balance - 500 WHERE id = 1;  -- debit
UPDATE accounts SET balance = balance + 500 WHERE id = 2;  -- credit

-- If both succeed:
COMMIT;

-- If something fails, undo everything:
ROLLBACK;
12

Primary & Foreign Keys

PRIMARY KEY
  • Uniquely identifies each row
  • Cannot be NULL
  • Only one per table
  • Often combined with AUTO_INCREMENT
FOREIGN KEY
  • References a PK in another table
  • Enforces referential integrity
  • Can be NULL (optional relationship)
  • Multiple FKs allowed per table
SQL
CREATE TABLE orders (
    id         INT AUTO_INCREMENT PRIMARY KEY,
    user_id    INT NOT NULL,
    total      DECIMAL(10,2),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- ON DELETE CASCADE: deleting a user also deletes their orders
-- ON DELETE SET NULL: sets user_id to NULL when user is deleted
13

SQL JOINs

JOINs combine rows from two or more tables based on a related column. The most tested SQL concept in interviews.

INNER JOIN
Only rows matching in both tables
LEFT JOIN
All from left + matching from right (NULL if no match)
RIGHT JOIN
All from right + matching from left (NULL if no match)
FULL JOIN
All rows from both tables (NULL where no match)
SQL
-- INNER JOIN: users who have placed orders
SELECT u.name, o.total
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

-- LEFT JOIN: ALL users, with orders if they exist
SELECT u.name, o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- Find users with NO orders
SELECT u.name
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.id IS NULL;

-- SELF JOIN: find users in the same department
SELECT a.name, b.name, a.department
FROM users a
JOIN users b ON a.department = b.department AND a.id != b.id;
14

UNION & Subqueries

SQL
-- UNION: combines results, removes duplicates
SELECT name FROM users
UNION
SELECT name FROM admin_users;

-- UNION ALL: keeps duplicates (faster)
SELECT name FROM users
UNION ALL
SELECT name FROM admin_users;

-- Subquery in WHERE
SELECT name, salary FROM users
WHERE salary > (SELECT AVG(salary) FROM users);

-- Subquery in FROM (derived table)
SELECT dept, avg_sal
FROM (
    SELECT department AS dept, AVG(salary) AS avg_sal
    FROM users GROUP BY department
) dept_avg
WHERE avg_sal > 80000;
15

Indexes & Performance

An index is a data structure (typically a B-Tree) that speeds up data retrieval at the cost of extra storage and slower writes. Think of it like a book's index — you find the page number without reading the whole book.

SQL
-- Create index on frequently queried column
CREATE INDEX idx_email ON users(email);

-- Composite index: column order matters!
CREATE INDEX idx_dept_salary ON users(department, salary);

-- EXPLAIN: see if index is being used
EXPLAIN SELECT * FROM users WHERE email = 'alice@example.com';

-- Drop index
DROP INDEX idx_email ON users;
Don't over-index. Each index slows down INSERT/UPDATE/DELETE because the index must be updated too. Index columns that appear in WHERE, JOIN ON, and ORDER BY clauses.
16

GROUP BY & HAVING

WHERE vs HAVING: WHERE filters rows before grouping. HAVING filters groups after aggregation. You cannot use aggregate functions in WHERE.
SQL
-- Count employees per department
SELECT department, COUNT(*) AS headcount
FROM users
GROUP BY department
ORDER BY headcount DESC;

-- HAVING: only departments with avg salary > 75k
SELECT department, ROUND(AVG(salary),2) AS avg_sal
FROM users
GROUP BY department
HAVING AVG(salary) > 75000
ORDER BY avg_sal DESC;

-- WHERE + GROUP BY + HAVING together
SELECT department, COUNT(*) AS cnt
FROM users
WHERE is_active = TRUE              -- filter rows first
GROUP BY department                 -- then group
HAVING COUNT(*) > 5               -- then filter groups
ORDER BY cnt DESC;                  -- then sort
17

Normalization

Normalization is the process of organizing a database to reduce redundancy and improve data integrity by dividing data into related tables.

1NF — FIRST NORMAL FORM
Eliminate repeating groups
Each column must hold atomic (indivisible) values. No arrays or comma-separated lists in a single cell. Each row must be unique.
2NF — SECOND NORMAL FORM
Remove partial dependencies
Must be in 1NF. Every non-key column must depend on the whole primary key — not just part of it. Relevant when PK is composite.
3NF — THIRD NORMAL FORM
Remove transitive dependencies
Must be in 2NF. Non-key columns must depend only on the primary key — not on other non-key columns. Move transitive data to its own table.
Interview tip: Most production schemas target 3NF. Sometimes denormalization is intentional for read-performance — know when to justify it.
Ready to test your SQL knowledge?
40+ SQL interview questions — joins, window functions, subqueries, indexes — tagged for FAANG and startups, with progress tracking.
SQL Interview Prep →