๐๏ธ SQL Complete Tutorial
Structured Query Language โ from basic SELECT queries to advanced stored procedures
What is SQL?
SQL (Structured Query Language) is the standard language for communicating with relational databases. It allows you to retrieve, insert, update, and delete data stored in tables.
Think of SQL as a way to ask questions to a database: “Give me all customers from New York” or “Show me the total sales for last month.”
Sample Database: Employees Table
| id | name | department | salary | city |
|---|---|---|---|---|
| 1 | Alice | IT | 75000 | New York |
| 2 | Bob | Sales | 65000 | Chicago |
| 3 | Charlie | IT | 82000 | New York |
The Basic SQL Query: SELECT and FROM
Every SQL query starts with SELECT (what columns you want) and FROM (which table contains the data). This is the simplest and most important SQL pattern.
Basic Syntax
SELECT column1, column2, column3 FROM table_name;
Example 1: Select specific columns
SELECT name, salary, city FROM employees;
Alice | 75000 | New York
Bob | 65000 | Chicago
Charlie | 82000 | New York
Example 2: Select ALL columns using * (asterisk)
SELECT * FROM employees;
SELECT * in production โ explicitly name columns for better performance and clarity.
Filtering Rows with WHERE
The WHERE clause filters rows based on a condition. Only rows that meet the condition are returned.
SELECT column1, column2 FROM table_name WHERE condition;
Example: Find IT employees
SELECT name, department, salary FROM employees WHERE department = 'IT';
Alice | IT | 75000
Charlie | IT | 82000
Comparison Operators
| Operator | Meaning | Example |
|---|---|---|
| = | Equal to | WHERE salary = 75000 |
| > | Greater than | WHERE salary > 70000 |
| < | Less than | WHERE salary < 80000 |
| >= | Greater than or equal | WHERE salary >= 65000 |
| <= | Less than or equal | WHERE salary <= 75000 |
| <> | Not equal | WHERE department <> 'Sales' |
Logical Operators: AND, OR, NOT, IN, BETWEEN
AND โ all conditions must be true
SELECT name, department, salary, city FROM employees WHERE department = 'IT' AND salary > 70000;
OR โ at least one condition must be true
SELECT name, city FROM employees WHERE city = 'New York' OR city = 'Chicago';
IN โ matches any value in a list
SELECT name, department
FROM employees
WHERE department IN ('IT', 'Sales');BETWEEN โ range filter (inclusive)
SELECT name, salary FROM employees WHERE salary BETWEEN 70000 AND 80000;
Sorting Results with ORDER BY
-- Ascending (lowest to highest, default) SELECT name, salary FROM employees ORDER BY salary ASC; -- Descending (highest to lowest) SELECT name, salary FROM employees ORDER BY salary DESC; -- Multiple columns SELECT name, department, salary FROM employees ORDER BY department ASC, salary DESC;
DISTINCT & LIMIT
DISTINCT removes duplicate rows. LIMIT restricts number of rows returned.
-- Get unique departments SELECT DISTINCT department FROM employees; -- Get top 2 highest paid employees SELECT name, salary FROM employees ORDER BY salary DESC LIMIT 2;
Aggregate Functions: COUNT, SUM, AVG, MIN, MAX
-- Count total employees SELECT COUNT(*) AS total_employees FROM employees; -- Average salary SELECT AVG(salary) AS average_salary FROM employees; -- Highest and lowest salary SELECT MAX(salary) AS highest, MIN(salary) AS lowest FROM employees; -- Total salary sum SELECT SUM(salary) AS payroll FROM employees;
GROUP BY & HAVING
GROUP BY groups rows that have the same values. HAVING filters groups (like WHERE for groups).
-- Average salary per department SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department; -- Departments with average salary above 70000 SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department HAVING AVG(salary) > 70000;
JOINS: Combining Multiple Tables
Real databases have many related tables. JOINs allow you to combine them.
INNER JOIN โ only matching rows
SELECT orders.id, customers.name, orders.total FROM orders INNER JOIN customers ON orders.customer_id = customers.id;
LEFT JOIN โ all rows from left table
SELECT customers.name, orders.total FROM customers LEFT JOIN orders ON customers.id = orders.customer_id;
UNION & UNION ALL
-- Combine results, remove duplicates SELECT city FROM customers UNION SELECT city FROM suppliers; -- Keep all duplicates SELECT city FROM customers UNION ALL SELECT city FROM suppliers;
Subqueries (Nested Queries)
A subquery is a query inside another query.
-- Find employees earning more than average SELECT name, salary FROM employees WHERE salary > (SELECT AVG(salary) FROM employees); -- EXISTS checks if subquery returns any rows SELECT name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id);
CASE โ Conditional Logic
SELECT name, salary,
CASE
WHEN salary >= 80000 THEN 'High'
WHEN salary >= 60000 THEN 'Medium'
ELSE 'Low'
END AS salary_level
FROM employees;INSERT INTO โ Adding Data
-- Insert specific columns
INSERT INTO employees (name, department, salary, city)
VALUES ('Diana', 'Marketing', 70000, 'Boston');
-- Insert all columns (order must match table)
INSERT INTO employees VALUES (4, 'Diana', 'Marketing', 70000, 'Boston');UPDATE & DELETE
-- Update specific rows UPDATE employees SET salary = 78000 WHERE name = 'Alice'; -- Delete specific rows DELETE FROM employees WHERE name = 'Bob';
NULL Values
NULL means missing or unknown data. Use IS NULL or IS NOT NULL (not = NULL).
SELECT * FROM employees WHERE bonus IS NULL; SELECT COALESCE(bonus, 0) AS bonus_amount FROM employees;
Stored Procedures
Reusable SQL code blocks that accept parameters.
-- MySQL syntax
DELIMITER //
CREATE PROCEDURE GetEmployeesByDept(IN dept_name VARCHAR(50))
BEGIN
SELECT * FROM employees WHERE department = dept_name;
END //
DELIMITER ;
-- Call the procedure
CALL GetEmployeesByDept('IT');๐ฏ Complete Query Example
-- Find top 3 departments by average salary (min 2 employees)
SELECT
department,
COUNT(*) AS emp_count,
AVG(salary) AS avg_salary,
MAX(salary) AS max_salary
FROM employees
WHERE city = 'New York'
GROUP BY department
HAVING COUNT(*) >= 2
ORDER BY avg_salary DESC
LIMIT 3;