SQL for Absolute Beginners
Create your first database, write SELECT queries, and filter data with WHERE from scratch.
Master databases and SQL from the ground up — from your first SELECT query to advanced joins, subqueries, and performance optimization.
SQL (Structured Query Language) is the universal language for working with relational databases. It powers everything from small apps to massive enterprise systems. Whether you are a developer, data analyst, or backend engineer, SQL is one of the most valuable skills you can learn.
SQL stands for Structured Query Language. It is used to create, read, update, and delete data in relational databases — collectively known as CRUD operations. Popular database systems that use SQL include:
Every SQL journey starts with understanding tables. A table is like a spreadsheet — it has columns (fields) and rows (records). Here is how you create one and insert data.
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(150) UNIQUE,
age INT,
course VARCHAR(50),
enrolled DATE
);
INSERT INTO students (name, email, age, course, enrolled)
VALUES
('Alice Johnson', 'alice@example.com', 20, 'Python', '2025-01-15'),
('Bob Smith', 'bob@example.com', 22, 'Web Dev', '2025-02-01'),
('Carla Reyes', 'carla@example.com', 19, 'Python', '2025-01-20'),
('David Lee', 'david@example.com', 21, 'SQL', '2025-03-10');
-- Select all columns
SELECT * FROM students;
-- Select specific columns
SELECT name, course FROM students;
-- Filter with WHERE
SELECT name, age FROM students WHERE age < 21;
-- Sort results
SELECT name, age FROM students ORDER BY age DESC;
-- Limit rows
SELECT name FROM students LIMIT 2;
The WHERE clause lets you filter rows using conditions. You can combine conditions with AND, OR, and NOT.
-- Single condition
SELECT * FROM students WHERE course = 'Python';
-- Multiple conditions
SELECT * FROM students WHERE course = 'Python' AND age <= 20;
-- OR condition
SELECT * FROM students WHERE course = 'SQL' OR course = 'Web Dev';
-- NOT condition
SELECT * FROM students WHERE NOT course = 'Python';
-- BETWEEN (inclusive range)
SELECT * FROM students WHERE age BETWEEN 19 AND 21;
-- IN (match a list)
SELECT * FROM students WHERE course IN ('Python', 'SQL');
-- LIKE (pattern matching)
SELECT * FROM students WHERE name LIKE 'A%'; -- starts with A
SELECT * FROM students WHERE email LIKE '%@example.com';
-- Update a record
UPDATE students SET age = 23 WHERE name = 'Bob Smith';
-- Update multiple columns
UPDATE students SET course = 'Data Science', age = 21 WHERE id = 3;
-- Delete a specific record
DELETE FROM students WHERE id = 4;
-- Delete all rows (keep table structure)
DELETE FROM students;
Aggregate functions perform calculations on a set of rows and return a single value. They are essential for data analysis.
-- Count total students
SELECT COUNT(*) AS total_students FROM students;
-- Average age
SELECT AVG(age) AS average_age FROM students;
-- Youngest and oldest
SELECT MIN(age) AS youngest, MAX(age) AS oldest FROM students;
-- Count students per course
SELECT course, COUNT(*) AS total
FROM students
GROUP BY course;
-- Filter groups with HAVING
SELECT course, COUNT(*) AS total
FROM students
GROUP BY course
HAVING COUNT(*) > 1;
JOINs combine rows from two or more tables based on a related column. This is the backbone of relational database design.
Let's say we have a second table:
CREATE TABLE enrollments (
enrollment_id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT,
course_name VARCHAR(50),
grade CHAR(2),
FOREIGN KEY (student_id) REFERENCES students(id)
);
INSERT INTO enrollments (student_id, course_name, grade)
VALUES (1, 'Python', 'A'), (2, 'Web Dev', 'B+'), (1, 'SQL', 'A-');
SELECT s.name, e.course_name, e.grade
FROM students s
INNER JOIN enrollments e ON s.id = e.student_id;
SELECT s.name, e.course_name, e.grade
FROM students s
LEFT JOIN enrollments e ON s.id = e.student_id;
SELECT s.name, e.course_name, e.grade
FROM students s
RIGHT JOIN enrollments e ON s.id = e.student_id;
-- Not supported in MySQL — use UNION of LEFT and RIGHT JOIN
SELECT s.name, e.course_name
FROM students s LEFT JOIN enrollments e ON s.id = e.student_id
UNION
SELECT s.name, e.course_name
FROM students s RIGHT JOIN enrollments e ON s.id = e.student_id;
A subquery is a query nested inside another query. It runs first and passes its result to the outer query.
-- Find students older than the average age
SELECT name, age FROM students
WHERE age > (SELECT AVG(age) FROM students);
-- Find students enrolled in at least one course
SELECT name FROM students
WHERE id IN (SELECT DISTINCT student_id FROM enrollments);
-- Subquery in SELECT (scalar subquery)
SELECT name,
(SELECT COUNT(*) FROM enrollments e WHERE e.student_id = s.id) AS total_courses
FROM students s;
Indexes speed up data retrieval on large tables. Think of them like a book index — instead of scanning every page, you jump straight to what you need.
-- Create an index on a column
CREATE INDEX idx_course ON students(course);
-- Create a unique index
CREATE UNIQUE INDEX idx_email ON students(email);
-- Drop an index
DROP INDEX idx_course ON students;
-- View indexes (MySQL)
SHOW INDEX FROM students;
A view is a saved SQL query you can treat like a virtual table. It simplifies complex queries and adds a layer of security by hiding raw table structure.
-- Create a view
CREATE VIEW python_students AS
SELECT name, age, email
FROM students
WHERE course = 'Python';
-- Query the view like a table
SELECT * FROM python_students;
-- Drop the view
DROP VIEW python_students;
Stored procedures are reusable blocks of SQL code stored in the database. They accept parameters and can contain logic like loops and conditionals.
-- Create a stored procedure (MySQL syntax)
DELIMITER $$
CREATE PROCEDURE GetStudentsByCourse(IN course_name VARCHAR(50))
BEGIN
SELECT name, age, email
FROM students
WHERE course = course_name;
END $$
DELIMITER ;
-- Call the procedure
CALL GetStudentsByCourse('Python');
Transactions group multiple SQL statements into a single unit. Either all statements succeed, or none do — this keeps your data consistent.
START TRANSACTION;
UPDATE students SET course = 'Data Science' WHERE id = 1;
INSERT INTO enrollments (student_id, course_name, grade)
VALUES (1, 'Data Science', 'A');
-- If everything is fine, save it
COMMIT;
-- If something went wrong, undo all changes
ROLLBACK;
Good database design prevents data duplication and keeps your data clean. The key principles are called normalization.
Understand what databases and tables are. Practice CREATE TABLE, INSERT, SELECT, WHERE, and ORDER BY until they feel natural.
Master UPDATE, DELETE, LIKE, BETWEEN, IN, and NULL handling. Build a small student or product database from scratch.
Use COUNT, SUM, AVG, MIN, MAX with GROUP BY and HAVING. Analyze data with aggregate queries on real datasets.
Design multi-table schemas with foreign keys. Practice INNER, LEFT, RIGHT, and FULL JOINs to combine related data.
Subqueries, views, indexes, transactions, and stored procedures. Optimize slow queries and understand execution plans.
Build a library management system, e-commerce database, or student portal. Connect SQL to a backend language like Python or Node.js.
Create your first database, write SELECT queries, and filter data with WHERE from scratch.
Master INNER, LEFT, RIGHT, and FULL JOINs with clear diagrams and real-world examples.
Analyze data using COUNT, SUM, AVG, MIN, MAX, and GROUP BY to summarize records.
Write nested queries, use EXISTS and IN operators, and tackle complex filtering problems.