| name | sql-fundamentals |
| description | Master SQL fundamentals including SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP operations. Learn data types, WHERE clauses, ORDER BY, GROUP BY, and basic joins. |
| sasmp_version | 1.3.0 |
| bonded_agent | 01-sql-fundamentals |
| bond_type | PRIMARY_BOND |
SQL Fundamentals
Quick Start
Your First SELECT Query
SELECT * FROM employees;
SELECT first_name, last_name, salary
FROM employees
WHERE salary > 50000;
SELECT first_name, last_name, salary
FROM employees
WHERE salary > 50000
ORDER BY salary DESC;
Core Concepts
Data Types
BIGINT, INT, SMALLINT, TINYINT
DECIMAL(10,2), FLOAT, DOUBLE
VARCHAR(255), CHAR(10), TEXT
DATE, TIME, TIMESTAMP, DATETIME
BOOLEAN, BLOB, JSON, UUID
DDL Operations (Data Definition Language)
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
salary DECIMAL(10,2),
hire_date DATE,
department_id INT,
FOREIGN KEY (department_id) REFERENCES departments(id)
);
ALTER TABLE employees ADD COLUMN phone VARCHAR(20);
ALTER TABLE employees MODIFY COLUMN salary DECIMAL(12,2);
ALTER TABLE employees DROP COLUMN phone;
DROP TABLE employees;
DML Operations (Data Manipulation Language)
INSERT INTO employees (first_name, last_name, salary)
VALUES ('John', 'Doe', 75000);
INSERT INTO employees (first_name, last_name, salary) VALUES
('Jane', 'Smith', 80000),
('Bob', 'Johnson', 70000);
UPDATE employees
SET salary = 85000
WHERE first_name = 'John';
DELETE FROM employees WHERE id = 1;
Query Filtering
SELECT * FROM employees WHERE salary > 50000;
SELECT * FROM employees WHERE salary BETWEEN 40000 AND 80000;
SELECT * FROM employees WHERE first_name IN ('John', 'Jane', 'Bob');
SELECT * FROM employees WHERE email IS NOT NULL;
SELECT * FROM employees WHERE first_name LIKE 'J%';
Sorting Results
SELECT * FROM employees ORDER BY salary DESC;
SELECT * FROM employees
ORDER BY department_id ASC, salary DESC;
SELECT * FROM employees
ORDER BY salary DESC
LIMIT 10;
Aggregate Functions
SELECT COUNT(*) as employee_count FROM employees;
SELECT SUM(salary) as total_salary FROM employees;
SELECT AVG(salary) as avg_salary FROM employees;
SELECT MIN(salary) as min_salary, MAX(salary) as max_salary FROM employees;
SELECT department_id, COUNT(*) as emp_count, AVG(salary) as avg_salary
FROM employees
GROUP BY department_id;
SELECT department_id, COUNT(*) as emp_count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5;
Basic JOINs
SELECT e.first_name, e.last_name, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;
SELECT e.first_name, e.last_name, d.department_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;
SELECT e.first_name, d.department_name, p.project_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id
INNER JOIN projects p ON e.id = p.employee_id;
Common String Functions
SELECT CONCAT(first_name, ' ', last_name) as full_name FROM employees;
SELECT first_name, LENGTH(first_name) as name_length FROM employees;
SELECT SUBSTRING(email, 1, POSITION('@' IN email)-1) as username FROM employees;
SELECT UPPER(first_name), LOWER(last_name) FROM employees;
SELECT TRIM(first_name) FROM employees;
Date Functions
SELECT CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP;
SELECT YEAR(hire_date), MONTH(hire_date), DAY(hire_date)
FROM employees;
SELECT first_name, hire_date,
DATEDIFF(CURRENT_DATE, hire_date) as days_employed
FROM employees;
SELECT first_name, hire_date,
DATE_ADD(hire_date, INTERVAL 1 YEAR) as one_year_anniversary
FROM employees;
Subqueries & Nested Queries
SELECT first_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
SELECT dept, avg_salary
FROM (
SELECT department_id as dept, AVG(salary) as avg_salary
FROM employees
GROUP BY department_id
) dept_averages
WHERE avg_salary > 70000;
SELECT first_name, department_id
FROM employees
WHERE department_id IN (
SELECT id FROM departments
WHERE location = 'New York'
);
SELECT d.department_name
FROM departments d
WHERE EXISTS (
SELECT 1 FROM employees e
WHERE e.department_id = d.id
AND e.salary > 100000
);
CASE Statements
SELECT first_name, salary,
CASE
WHEN salary < 50000 THEN 'Junior'
WHEN salary < 80000 THEN 'Mid-Level'
WHEN salary < 120000 THEN 'Senior'
ELSE 'Executive'
END as level
FROM employees;
SELECT first_name, salary, years_employed,
CASE
WHEN years_employed >= 10 AND salary > 100000 THEN 'Senior Executive'
WHEN years_employed >= 5 AND salary > 75000 THEN 'Senior Staff'
WHEN salary > 60000 THEN 'Mid-Level'
ELSE 'Junior'
END as category
FROM employees;
SELECT department_id,
( salary ) high_earners,
( salary ) low_earners
employees
department_id;
NULL Handling
SELECT first_name,
COALESCE(phone, 'No Phone', 'Unknown') as contact
FROM employees;
SELECT first_name,
NULLIF(salary, 0) as salary
FROM employees;
SELECT first_name,
IFNULL(bonus, 0) as bonus_amount
FROM employees;
SELECT first_name FROM employees
WHERE phone IS NULL;
Distinct & Duplicates
SELECT DISTINCT department_id FROM employees;
SELECT COUNT(DISTINCT department_id) as unique_departments
FROM employees;
SELECT email, COUNT(*) as count
FROM employees
GROUP BY email
HAVING COUNT(*) > 1;
Union & Set Operations
SELECT first_name FROM employees WHERE salary > 100000
UNION
SELECT first_name FROM contractors WHERE hourly_rate > 100;
SELECT first_name FROM employees
UNION ALL
SELECT first_name FROM contractors;
SELECT department_id FROM employees
INTERSECT
SELECT department_id FROM projects;
SELECT employee_id FROM employees
EXCEPT
SELECT employee_id FROM time_off;
Window Functions (Introduction)
SELECT first_name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) as rank
FROM employees;
SELECT first_name, department_id, salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) as dept_rank
FROM employees;
SELECT first_name, salary,
SUM(salary) OVER (ORDER BY id) as running_total
FROM employees;
SELECT first_name, salary,
LAG(salary) OVER (ORDER BY id) as prev_salary,
LEAD(salary) OVER (ORDER BY id) as next_salary
FROM employees;
Common SQL Patterns
Employee Salaries Problem
SELECT e.first_name, e.salary
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id
WHERE e.salary > m.salary;
SELECT department_id, first_name, salary
FROM (
SELECT department_id, first_name, salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) as rn
FROM employees
) ranked
WHERE rn = 1;
Sales & Orders
SELECT DATE_TRUNC('month', order_date) as month,
SUM(total_amount) as monthly_total
FROM orders
GROUP BY DATE_TRUNC('month', order_date)
ORDER BY month;
SELECT customer_id, COUNT(order_id) as num_orders,
SUM(total_amount) as lifetime_value
FROM orders
GROUP BY customer_id
ORDER BY lifetime_value DESC;
SELECT product_id, product_name
FROM products
WHERE product_id NOT IN (
SELECT DISTINCT product_id FROM order_items
);
Performance Tips
CREATE INDEX idx_employee_dept ON employees(department_id);
CREATE INDEX idx_order_date ON orders(order_date);
SELECT id, first_name, last_name FROM employees;
SELECT * FROM employees;
SELECT *
FROM employees e
WHERE e.department_id = 1
INNER JOIN departments d ON e.department_id = d.id;
SELECT * FROM large_table LIMIT 100;
Next Steps
Learn Advanced SQL including CTEs, complex window functions, and query optimization in the advanced-sql skill.