11. Database Design and Modeling
13. Data Definition Language (DDL)
MySQL Tutorial - 12. SQL Queries

12.1 Introduction to SQL Queries

Overview of SQL (Structured Query Language)

SQL (Structured Query Language) is a standardized programming language used to manage and manipulate relational databases. MySQL is one of the most popular relational database management systems (RDBMS) that uses SQL as its primary interface. Here's an overview of SQL in MySQL with code examples:

  1. Creating a Database:
CREATE DATABASE mydatabase;
  1. Using a Database:
USE mydatabase;
  1. Creating a Table:
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
  1. Inserting Data:
INSERT INTO users (username, email) VALUES ('john_doe', 'john@example.com'); INSERT INTO users (username, email) VALUES ('jane_doe', 'jane@example.com');
  1. Selecting Data:
SELECT * FROM users;
  1. Filtering Data:
SELECT * FROM users WHERE username = 'john_doe';
  1. Updating Data:
UPDATE users SET email = 'john.doe@example.com' WHERE username = 'john_doe';
  1. Deleting Data:
DELETE FROM users WHERE username = 'jane_doe';
  1. Sorting Data:
SELECT * FROM users ORDER BY created_at DESC;
  1. Limiting Results:
SELECT * FROM users LIMIT 5;
  1. Joining Tables:
SELECT users.username, orders.product_name FROM users INNER JOIN orders ON users.id = orders.user_id;
  1. Grouping Data:
SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id;
  1. Adding Indexes:
CREATE INDEX idx_username ON users (username);
  1. Transactions:
START TRANSACTION; -- SQL statements COMMIT;
  1. Views:
CREATE VIEW user_orders AS SELECT users.username, orders.product_name FROM users INNER JOIN orders ON users.id = orders.user_id;
  1. Stored Procedures:
DELIMITER $$ CREATE PROCEDURE get_user(IN user_id INT) BEGIN SELECT * FROM users WHERE id = user_id; END$$ DELIMITER ;

These are just some basic SQL commands and concepts in MySQL. SQL is a powerful language with many more features and capabilities for managing and querying data in relational databases.

Importance of SQL in database management

SQL plays a crucial role in database management, especially in MySQL. Here are some key reasons why SQL is important in MySQL database management along with examples:

  1. Data Manipulation: SQL allows users to manipulate data stored in MySQL databases. This includes inserting, updating, deleting, and querying data.

    Example:

    -- Inserting data INSERT INTO users (username, email) VALUES ('john_doe', 'john@example.com'); -- Updating data UPDATE users SET email = 'john.doe@example.com' WHERE username = 'john_doe'; -- Deleting data DELETE FROM users WHERE username = 'john_doe'; -- Querying data SELECT * FROM users WHERE username = 'john_doe';
  2. Data Definition: SQL enables users to define the structure of databases, tables, and other database objects in MySQL.

    Example:

    -- Creating a table CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL );
  3. Data Control: SQL provides mechanisms for controlling access to data in MySQL databases through permissions and security features.

    Example:

    -- Granting privileges GRANT SELECT, INSERT ON mydatabase.* TO 'user'@'localhost' IDENTIFIED BY 'password'; -- Revoking privileges REVOKE DELETE ON mydatabase.* FROM 'user'@'localhost';
  4. Data Retrieval and Reporting: SQL allows users to retrieve data from MySQL databases based on various criteria and generate reports.

    Example:

    -- Retrieving data SELECT * FROM users WHERE username LIKE 'j%'; -- Generating reports SELECT YEAR(created_at) AS year, COUNT(*) AS total_users FROM users GROUP BY YEAR(created_at);
  5. Data Integrity: SQL supports the enforcement of data integrity rules such as constraints and foreign key relationships to maintain the quality and consistency of data in MySQL databases.

    Example:

    -- Adding a foreign key constraint ALTER TABLE orders ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id);
  6. Data Transactions: SQL allows users to execute multiple SQL statements as a single unit of work, ensuring data consistency and integrity through transactions.

    Example:

    START TRANSACTION; -- SQL statements COMMIT;

SQL serves as the standard language for interacting with MySQL databases, providing a comprehensive set of commands and features for efficient database management, data manipulation, and data retrieval. Its importance lies in its versatility, ease of use, and ability to handle complex database operations effectively.

Basic SQL syntax and commands

Certainly! Here are some basic SQL syntax and commands commonly used in MySQL, along with examples:

  1. Creating a Database:
CREATE DATABASE mydatabase;

Example:

CREATE DATABASE employees;
  1. Using a Database:
USE mydatabase;

Example:

USE employees;
  1. Creating a Table:
CREATE TABLE employees ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), age INT, department VARCHAR(50) );

Example:

CREATE TABLE employees ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), age INT, department VARCHAR(50) );
  1. Inserting Data:
INSERT INTO employees (name, age, department) VALUES ('John Doe', 30, 'IT');

Example:

INSERT INTO employees (name, age, department) VALUES ('Jane Smith', 35, 'HR');
  1. Selecting Data:
SELECT * FROM employees;

Example:

SELECT * FROM employees;
  1. Filtering Data:
SELECT * FROM employees WHERE department = 'IT';

Example:

SELECT * FROM employees WHERE age > 25;
  1. Updating Data:
UPDATE employees SET age = 40 WHERE name = 'John Doe';

Example:

UPDATE employees SET department = 'Finance' WHERE name = 'Jane Smith';
  1. Deleting Data:
DELETE FROM employees WHERE name = 'John Doe';

Example:

DELETE FROM employees WHERE age > 50;
  1. Sorting Data:
SELECT * FROM employees ORDER BY age DESC;

Example:

SELECT * FROM employees ORDER BY name ASC;
  1. Limiting Results:
SELECT * FROM employees LIMIT 5;

Example:

SELECT * FROM employees LIMIT 10 OFFSET 5;

These are some of the basic SQL commands and syntax used in MySQL. They provide the foundation for interacting with databases, manipulating data, and retrieving information effectively.


12.2 SELECT Statement

Retrieving data from a single table using SELECT

Certainly! Retrieving data from a single table using the SELECT statement is one of the fundamental operations in SQL. Here's how you can do it with examples:

  1. Selecting All Columns: To retrieve all columns from a table, you can use the SELECT * syntax.

    SELECT * FROM tablename;

    Example:

    SELECT * FROM employees;

    This retrieves all columns and rows from the employees table.

  2. Selecting Specific Columns: To retrieve specific columns from a table, list the column names after the SELECT keyword.

    SELECT column1, column2 FROM tablename;

    Example:

    SELECT name, age FROM employees;

    This retrieves only the name and age columns from the employees table.

  3. Filtering Data with WHERE Clause: You can use the WHERE clause to filter rows based on specific conditions.

    SELECT * FROM tablename WHERE condition;

    Example:

    SELECT * FROM employees WHERE department = 'IT';

    This retrieves all columns and rows from the employees table where the department is 'IT'.

  4. Sorting Data with ORDER BY: You can use the ORDER BY clause to sort the results based on one or more columns.

    SELECT * FROM tablename ORDER BY column ASC|DESC;

    Example:

    SELECT * FROM employees ORDER BY age DESC;

    This retrieves all columns and rows from the employees table sorted by age in descending order.

  5. Limiting Results with LIMIT: You can use the LIMIT clause to restrict the number of rows returned.

    SELECT * FROM tablename LIMIT count;

    Example:

    SELECT * FROM employees LIMIT 10;

    This retrieves the first 10 rows from the employees table.

  6. Combining Conditions with AND, OR, NOT: You can use logical operators like AND, OR, and NOT to combine multiple conditions in the WHERE clause.

    SELECT * FROM tablename WHERE condition1 AND|OR|NOT condition2;

    Example:

    SELECT * FROM employees WHERE department = 'IT' AND age > 30;

    This retrieves all columns and rows from the employees table where the department is 'IT' and age is greater than 30.

These are some common examples of retrieving data from a single table using the SELECT statement in MySQL. The SELECT statement is powerful and versatile, allowing you to fetch the data you need with various filtering, sorting, and limiting options.

Specifying columns in the SELECT clause

Specifying columns in the SELECT clause allows you to retrieve only the data you need from a table. Here's how you can do it with examples:

  1. Selecting Specific Columns: To retrieve specific columns from a table, list the column names after the SELECT keyword.

    SELECT column1, column2 FROM tablename;

    Example:

    SELECT name, age FROM employees;

    This retrieves only the name and age columns from the employees table.

  2. Alias Columns: You can use aliases to rename columns in the result set.

    SELECT column1 AS alias1, column2 AS alias2 FROM tablename;

    Example:

    SELECT name AS employee_name, age AS employee_age FROM employees;

    This retrieves the name column as employee_name and the age column as employee_age from the employees table.

  3. Expression in SELECT: You can use expressions in the SELECT clause, such as arithmetic operations or concatenation.

    SELECT expression AS alias FROM tablename;

    Example:

    SELECT name, age, age * 12 AS age_in_months FROM employees;

    This calculates the age_in_months by multiplying the age column by 12 and retrieves it along with the name and age columns from the employees table.

  4. Using Aggregate Functions: You can use aggregate functions like COUNT, SUM, AVG, MIN, MAX, etc., in the SELECT clause to perform calculations on a set of rows.

    SELECT aggregate_function(column) FROM tablename;

    Example:

    SELECT COUNT(*) AS total_employees FROM employees;

    This calculates the total number of employees in the employees table.

  5. Combining Columns and Expressions: You can combine columns and expressions in the SELECT clause.

    SELECT column1, expression AS alias FROM tablename;

    Example:

    SELECT name, CONCAT('Age: ', age) AS age_info FROM employees;

    This retrieves the name column along with a concatenated string that includes the age information from the employees table.

  6. Using DISTINCT: You can use the DISTINCT keyword to retrieve unique values from a column.

    SELECT DISTINCT column FROM tablename;

    Example:

    SELECT DISTINCT department FROM employees;

    This retrieves unique department names from the employees table.

These examples demonstrate various ways to specify columns in the SELECT clause in MySQL. By selecting only the necessary columns, you can optimize query performance and reduce network overhead.

Using aliases for column names

Using aliases for column names in MySQL allows you to rename the columns returned in the query result. Here's how you can use aliases with examples:

  1. Basic Alias Syntax: You can use the AS keyword to assign an alias to a column name.

    SELECT column_name AS alias_name FROM tablename;

    Example:

    SELECT name AS employee_name, age AS employee_age FROM employees;

    This renames the name column to employee_name and the age column to employee_age in the result set.

  2. Alias with Table Alias: When dealing with multiple tables or subqueries, you can use table aliases along with column aliases.

    SELECT t1.column_name AS alias_name FROM tablename1 t1 JOIN tablename2 t2 ON t1.column_id = t2.column_id;

    Example:

    SELECT e.name AS employee_name, d.name AS department_name FROM employees e JOIN departments d ON e.department_id = d.id;

    This renames the name column from the employees table to employee_name and the name column from the departments table to department_name in the result set.

  3. Alias with Expressions: You can also use aliases for expressions in the SELECT clause.

    SELECT expression AS alias_name FROM tablename;

    Example:

    SELECT name, age, CONCAT('Age: ', age) AS age_info FROM employees;

    This concatenates the string 'Age: ' with the age column and assigns the alias age_info to the resulting expression.

  4. Using Aliases in Aggregate Functions: You can assign aliases to the results of aggregate functions.

    SELECT COUNT(*) AS total_employees FROM tablename;

    Example:

    SELECT COUNT(*) AS total_employees FROM employees;

    This calculates the total number of employees and assigns the alias total_employees to the result.

  5. Using Aliases in Subqueries: Aliases can be used to reference columns in subqueries.

    SELECT (SELECT column_name FROM tablename) AS alias_name FROM othertablename;

    Example:

    SELECT (SELECT AVG(age) FROM employees) AS avg_age FROM dual;

    This calculates the average age of employees and assigns the alias avg_age to the result.

Using aliases in MySQL makes query results more readable and provides meaningful names for columns or expressions in the result set. It also allows you to reference columns easily, especially in cases involving multiple tables or complex expressions.


12.3 WHERE Clause

Filtering data using the WHERE clause

Filtering data using the WHERE clause in MySQL allows you to specify conditions that determine which rows to retrieve from a table. Here's how you can filter data using the WHERE clause with examples:

  1. Basic WHERE Syntax: You can use the WHERE clause to specify conditions that rows must meet to be included in the result set.

    SELECT column1, column2 FROM tablename WHERE condition;

    Example:

    SELECT * FROM employees WHERE department = 'IT';

    This retrieves all columns and rows from the employees table where the department is 'IT'.

  2. Comparison Operators: You can use comparison operators such as =, <>, >, <, >=, <=, etc., in the WHERE clause.

    SELECT * FROM tablename WHERE column > value;

    Example:

    SELECT * FROM employees WHERE age > 30;

    This retrieves all columns and rows from the employees table where the age is greater than 30.

  3. Logical Operators (AND, OR, NOT): You can combine multiple conditions using logical operators AND, OR, and NOT in the WHERE clause.

    SELECT * FROM tablename WHERE condition1 AND|OR|NOT condition2;

    Example:

    SELECT * FROM employees WHERE department = 'IT' AND age > 30;

    This retrieves all columns and rows from the employees table where the department is 'IT' and the age is greater than 30.

  4. IN Operator: You can use the IN operator to specify multiple values for a column.

    SELECT * FROM tablename WHERE column IN (value1, value2, ...);

    Example:

    SELECT * FROM employees WHERE department IN ('IT', 'HR');

    This retrieves all columns and rows from the employees table where the department is either 'IT' or 'HR'.

  5. LIKE Operator: You can use the LIKE operator with wildcard characters % and _ to perform pattern matching.

    SELECT * FROM tablename WHERE column LIKE pattern;

    Example:

    SELECT * FROM employees WHERE name LIKE 'J%';

    This retrieves all columns and rows from the employees table where the name starts with 'J'.

  6. NULL Values: You can filter rows based on NULL values using the IS NULL and IS NOT NULL operators.

    SELECT * FROM tablename WHERE column IS NULL|IS NOT NULL;

    Example:

    SELECT * FROM employees WHERE department IS NULL;

    This retrieves all columns and rows from the employees table where the department is NULL.

Using the WHERE clause in MySQL allows you to retrieve specific subsets of data from a table based on specified conditions, making your queries more targeted and efficient.

Comparison operators (e.g., =, <>, <, >, BETWEEN, LIKE)

Certainly! Comparison operators in MySQL are used in the WHERE clause to specify conditions for filtering data based on comparison with values or other columns. Here are some commonly used comparison operators along with examples:

  1. Equal to (=): Matches values that are equal.

    SELECT * FROM tablename WHERE column = value;

    Example:

    SELECT * FROM employees WHERE department = 'IT';
  2. Not equal to (<> or !=): Matches values that are not equal.

    SELECT * FROM tablename WHERE column <> value;

    Example:

    SELECT * FROM employees WHERE department <> 'HR';
  3. Greater than (>): Matches values that are greater than the specified value.

    SELECT * FROM tablename WHERE column > value;

    Example:

    SELECT * FROM employees WHERE age > 30;
  4. Less than (<): Matches values that are less than the specified value.

    SELECT * FROM tablename WHERE column < value;

    Example:

    SELECT * FROM employees WHERE salary < 50000;
  5. Greater than or equal to (>=): Matches values that are greater than or equal to the specified value.

    SELECT * FROM tablename WHERE column >= value;

    Example:

    SELECT * FROM employees WHERE age >= 25;
  6. Less than or equal to (<=): Matches values that are less than or equal to the specified value.

    SELECT * FROM tablename WHERE column <= value;

    Example:

    SELECT * FROM employees WHERE salary <= 100000;
  7. Between (BETWEEN): Matches values within a range.

    SELECT * FROM tablename WHERE column BETWEEN value1 AND value2;

    Example:

    SELECT * FROM employees WHERE age BETWEEN 25 AND 40;
  8. Like (LIKE): Matches values similar to a specified pattern using wildcard characters % and _.

    SELECT * FROM tablename WHERE column LIKE pattern;

    Example:

    SELECT * FROM employees WHERE name LIKE 'J%';

    This retrieves all rows from the employees table where the name column starts with 'J'.

These comparison operators allow you to create flexible and precise conditions for filtering data in MySQL queries, making it easy to retrieve the specific data you need from your database tables.

Logical operators (e.g., AND, OR, NOT)

Logical operators in MySQL, including AND, OR, and NOT, are used to combine multiple conditions in the WHERE clause to filter data based on complex criteria. Here's how you can use logical operators in MySQL queries along with examples:

  1. AND Operator: The AND operator is used to combine multiple conditions, and it requires both conditions to be true for the row to be included in the result set.

    SELECT * FROM tablename WHERE condition1 AND condition2;

    Example:

    SELECT * FROM employees WHERE department = 'IT' AND age > 30;

    This retrieves all rows from the employees table where the department is 'IT' and the age is greater than 30.

  2. OR Operator: The OR operator is used to combine multiple conditions, and it requires at least one of the conditions to be true for the row to be included in the result set.

    SELECT * FROM tablename WHERE condition1 OR condition2;

    Example:

    SELECT * FROM employees WHERE department = 'IT' OR department = 'HR';

    This retrieves all rows from the employees table where the department is either 'IT' or 'HR'.

  3. NOT Operator: The NOT operator is used to negate a condition, returning rows that do not satisfy the specified condition.

    SELECT * FROM tablename WHERE NOT condition;

    Example:

    SELECT * FROM employees WHERE NOT department = 'IT';

    This retrieves all rows from the employees table where the department is not 'IT'.

  4. Combining Logical Operators: You can combine AND, OR, and NOT operators to create complex conditions.

    SELECT * FROM tablename WHERE condition1 AND (condition2 OR condition3) AND NOT condition4;

    Example:

    SELECT * FROM employees WHERE department = 'IT' AND (age > 30 OR salary > 100000) AND NOT name = 'John';

    This retrieves all rows from the employees table where the department is 'IT', the age is greater than 30 or the salary is greater than 100,000, and the name is not 'John'.

Logical operators in MySQL allow you to create sophisticated conditions for filtering data in your queries, enabling you to retrieve the specific subsets of data you need from your database tables.


12.4 ORDER BY Clause

Sorting query results using ORDER BY

Sorting query results using the ORDER BY clause in MySQL allows you to specify the order in which rows should be returned based on one or more columns. Here's how you can use the ORDER BY clause with examples:

  1. Sorting by Single Column: You can sort the query results based on a single column in ascending or descending order.

    SELECT * FROM tablename ORDER BY column ASC|DESC;

    Example:

    SELECT * FROM employees ORDER BY age DESC;

    This retrieves all columns and rows from the employees table and sorts them based on the age column in descending order.

  2. Sorting by Multiple Columns: You can sort the query results based on multiple columns, where the primary sort is based on the first column specified, and subsequent columns are used as tie-breakers.

    SELECT * FROM tablename ORDER BY column1 ASC|DESC, column2 ASC|DESC, ...;

    Example:

    SELECT * FROM employees ORDER BY department ASC, age DESC;

    This retrieves all columns and rows from the employees table and sorts them first by the department column in ascending order and then by the age column in descending order.

  3. Sorting with NULL Values: By default, NULL values are sorted at the end of the result set when sorting in ascending order and at the beginning when sorting in descending order. You can use the NULLS FIRST or NULLS LAST options to control the placement of NULL values.

    SELECT * FROM tablename ORDER BY column ASC|DESC NULLS FIRST|LAST;

    Example:

    SELECT * FROM employees ORDER BY department ASC NULLS FIRST, age DESC;

    This retrieves all columns and rows from the employees table and sorts them by the department column in ascending order, with NULL values appearing first, and then by the age column in descending order.

  4. Sorting with Expressions: You can also sort query results based on expressions or calculated values.

    SELECT * FROM tablename ORDER BY expression ASC|DESC;

    Example:

    SELECT * FROM employees ORDER BY salary * 12 DESC;

    This retrieves all columns and rows from the employees table and sorts them based on the annual salary calculated by multiplying the salary column by 12 in descending order.

Sorting query results using the ORDER BY clause in MySQL allows you to arrange data in a specific order, making it easier to analyze and understand the results returned by your queries.

Sorting by multiple columns

Sorting by multiple columns in MySQL allows you to specify a primary sort order followed by secondary sort orders for tie-breaking. Here's how you can use the ORDER BY clause to sort by multiple columns with examples:

  1. Sorting by Multiple Columns: You can sort query results based on multiple columns by listing them in the ORDER BY clause, where the primary sort is based on the first column specified, and subsequent columns are used as tie-breakers.

    SELECT * FROM tablename ORDER BY column1 ASC|DESC, column2 ASC|DESC, ...;

    Example:

    SELECT * FROM employees ORDER BY department ASC, age DESC;

    This retrieves all columns and rows from the employees table and sorts them first by the department column in ascending order and then by the age column in descending order.

  2. Sorting by Multiple Columns with Different Orders: You can specify different sort orders for different columns.

    SELECT * FROM tablename ORDER BY column1 ASC|DESC, column2 DESC|ASC, ...;

    Example:

    SELECT * FROM employees ORDER BY department ASC, age DESC, salary ASC;

    This retrieves all columns and rows from the employees table and sorts them first by the department column in ascending order, then by the age column in descending order, and finally by the salary column in ascending order.

  3. Sorting with NULL Values: By default, NULL values are sorted at the end of the result set when sorting in ascending order and at the beginning when sorting in descending order. You can use the NULLS FIRST or NULLS LAST options to control the placement of NULL values.

    SELECT * FROM tablename ORDER BY column ASC|DESC NULLS FIRST|LAST, ...;

    Example:

    SELECT * FROM employees ORDER BY department ASC NULLS FIRST, age DESC;

    This retrieves all columns and rows from the employees table and sorts them by the department column in ascending order, with NULL values appearing first, and then by the age column in descending order.

Sorting by multiple columns in MySQL allows you to precisely control the order in which query results are returned, enabling you to organize data effectively for analysis and presentation.

Specifying ascending and descending order

In MySQL, you can specify the desired order of sorting using the ASC (ascending) and DESC (descending) keywords in the ORDER BY clause. Here's how you can use them with examples:

  1. Ascending Order (ASC): Sorts the query result in ascending order (from smallest to largest or from A to Z).

    SELECT * FROM tablename ORDER BY column ASC;

    Example:

    SELECT * FROM employees ORDER BY age ASC;

    This retrieves all columns and rows from the employees table and sorts them by the age column in ascending order.

  2. Descending Order (DESC): Sorts the query result in descending order (from largest to smallest or from Z to A).

    SELECT * FROM tablename ORDER BY column DESC;

    Example:

    SELECT * FROM employees ORDER BY salary DESC;

    This retrieves all columns and rows from the employees table and sorts them by the salary column in descending order.

  3. Combining ASC and DESC: You can specify different sorting orders for different columns in the ORDER BY clause.

    SELECT * FROM tablename ORDER BY column1 ASC|DESC, column2 DESC|ASC, ...;

    Example:

    SELECT * FROM employees ORDER BY department ASC, age DESC;

    This retrieves all columns and rows from the employees table and sorts them first by the department column in ascending order and then by the age column in descending order.

  4. Sorting with NULL Values: By default, NULL values are sorted at the end of the result set when sorting in ascending order and at the beginning when sorting in descending order. You can use the NULLS FIRST or NULLS LAST options to control the placement of NULL values.

    SELECT * FROM tablename ORDER BY column ASC|DESC NULLS FIRST|LAST, ...;

    Example:

    SELECT * FROM employees ORDER BY department ASC NULLS FIRST, age DESC;

    This retrieves all columns and rows from the employees table and sorts them by the department column in ascending order, with NULL values appearing first, and then by the age column in descending order.

Specifying ascending and descending order in MySQL allows you to precisely control the sorting behavior of your query results, ensuring that they are ordered exactly as needed for your application or analysis.


12.5 Aggregate Functions

Calculating aggregate values (e.g., SUM, AVG, COUNT, MAX, MIN)

In MySQL, aggregate functions are used to perform calculations on a set of values and return a single result. Here's how you can use some common aggregate functions with examples:

  1. SUM(): Calculates the sum of all values in a column.

    SELECT SUM(column_name) FROM tablename;

    Example:

    SELECT SUM(salary) AS total_salary FROM employees;

    This calculates the total salary of all employees.

  2. AVG(): Calculates the average of all values in a column.

    SELECT AVG(column_name) FROM tablename;

    Example:

    SELECT AVG(age) AS avg_age FROM employees;

    This calculates the average age of all employees.

  3. COUNT(): Counts the number of rows returned by a query.

    SELECT COUNT(*) FROM tablename;

    Example:

    SELECT COUNT(*) AS total_employees FROM employees;

    This counts the total number of employees.

  4. MAX(): Returns the maximum value in a column.

    SELECT MAX(column_name) FROM tablename;

    Example:

    SELECT MAX(salary) AS max_salary FROM employees;

    This finds the maximum salary among all employees.

  5. MIN(): Returns the minimum value in a column.

    SELECT MIN(column_name) FROM tablename;

    Example:

    SELECT MIN(age) AS min_age FROM employees;

    This finds the minimum age among all employees.

  6. Combining Aggregate Functions: You can also combine aggregate functions with other columns or expressions.

    SELECT AVG(column1), SUM(column2) FROM tablename;

    Example:

    SELECT AVG(age) AS avg_age, SUM(salary) AS total_salary FROM employees;

    This calculates the average age and total salary of all employees.

Aggregate functions in MySQL are powerful tools for performing calculations and obtaining summary information from your data. They enable you to derive insights and perform analysis on large datasets efficiently.

Using aggregate functions with GROUP BY clause

Using aggregate functions with the GROUP BY clause in MySQL allows you to perform calculations on groups of rows and obtain summary information for each group. Here's how you can use aggregate functions with the GROUP BY clause with examples:

  1. GROUP BY with COUNT(): Calculates the number of rows in each group.

    SELECT column1, COUNT(*) FROM tablename GROUP BY column1;

    Example:

    SELECT department, COUNT(*) AS num_employees FROM employees GROUP BY department;

    This counts the number of employees in each department.

  2. GROUP BY with SUM(): Calculates the sum of values in each group.

    SELECT column1, SUM(column2) FROM tablename GROUP BY column1;

    Example:

    SELECT department, SUM(salary) AS total_salary FROM employees GROUP BY department;

    This calculates the total salary for each department.

  3. GROUP BY with AVG(): Calculates the average of values in each group.

    SELECT column1, AVG(column2) FROM tablename GROUP BY column1;

    Example:

    SELECT department, AVG(age) AS avg_age FROM employees GROUP BY department;

    This calculates the average age for each department.

  4. GROUP BY with MAX(): Finds the maximum value in each group.

    SELECT column1, MAX(column2) FROM tablename GROUP BY column1;

    Example:

    SELECT department, MAX(salary) AS max_salary FROM employees GROUP BY department;

    This finds the maximum salary for each department.

  5. GROUP BY with MIN(): Finds the minimum value in each group.

    SELECT column1, MIN(column2) FROM tablename GROUP BY column1;

    Example:

    SELECT department, MIN(age) AS min_age FROM employees GROUP BY department;

    This finds the minimum age for each department.

  6. Combining GROUP BY with WHERE Clause: You can combine the GROUP BY clause with the WHERE clause to filter data before grouping.

    SELECT column1, AVG(column2) FROM tablename WHERE condition GROUP BY column1;

    Example:

    SELECT department, AVG(salary) AS avg_salary FROM employees WHERE age > 30 GROUP BY department;

    This calculates the average salary for each department among employees older than 30.

Using aggregate functions with the GROUP BY clause in MySQL allows you to summarize data based on groups defined by one or more columns. It's a powerful tool for analyzing data and gaining insights into patterns within your dataset.

Filtering grouped data with HAVING clause

In MySQL, the HAVING clause is used to filter groups of rows returned by the GROUP BY clause based on specified conditions. It is similar to the WHERE clause but is applied to groups rather than individual rows. Here's how you can use the HAVING clause with examples:

  1. Basic HAVING Clause Syntax: You can use the HAVING clause to filter groups based on aggregate functions or grouped column values.

    SELECT column1, aggregate_function(column2) FROM tablename GROUP BY column1 HAVING condition;

    Example:

    SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department HAVING AVG(salary) > 50000;

    This retrieves the average salary for each department and filters out departments where the average salary is greater than $50,000.

  2. Using Aggregate Functions in HAVING Clause: You can use aggregate functions in the HAVING clause to filter groups based on calculated values.

    SELECT column1, aggregate_function(column2) FROM tablename GROUP BY column1 HAVING aggregate_function(column2) > value;

    Example:

    SELECT department, COUNT(*) AS num_employees FROM employees GROUP BY department HAVING COUNT(*) > 10;

    This counts the number of employees in each department and filters out departments with more than 10 employees.

  3. Combining HAVING with WHERE Clause: You can combine the HAVING clause with the WHERE clause to filter data before and after grouping.

    SELECT column1, aggregate_function(column2) FROM tablename WHERE condition GROUP BY column1 HAVING condition;

    Example:

    SELECT department, AVG(salary) AS avg_salary FROM employees WHERE age > 30 GROUP BY department HAVING AVG(salary) > 50000;

    This filters out employees older than 30, calculates the average salary for each department, and then filters out departments where the average salary is greater than $50,000.

The HAVING clause in MySQL allows you to filter groups of rows based on aggregate values, providing additional control over the output of grouped data. It's particularly useful when you need to apply conditions to groups after they have been formed using the GROUP BY clause.


12.6 Joins

Performing inner joins between tables

Performing inner joins between tables in MySQL allows you to combine rows from two or more tables based on a related column between them. Here's how you can perform inner joins with examples:

  1. Basic Inner Join Syntax: You can perform an inner join between two tables using the INNER JOIN clause and specifying the joining condition in the ON clause.

    SELECT columns FROM table1 INNER JOIN table2 ON table1.column = table2.column;

    Example:

    SELECT employees.name, departments.department_name FROM employees INNER JOIN departments ON employees.department_id = departments.id;

    This retrieves the name of employees along with their corresponding department names by joining the employees table with the departments table based on the department_id column.

  2. Joining Multiple Tables: You can join more than two tables by adding additional INNER JOIN clauses and joining conditions.

    SELECT columns FROM table1 INNER JOIN table2 ON table1.column1 = table2.column1 INNER JOIN table3 ON table2.column2 = table3.column2;

    Example:

    SELECT orders.order_id, customers.customer_name, products.product_name FROM orders INNER JOIN customers ON orders.customer_id = customers.customer_id INNER JOIN products ON orders.product_id = products.product_id;

    This retrieves the order ID, customer name, and product name by joining the orders table with the customers and products tables based on their respective IDs.

  3. Aliasing Tables: You can use table aliases to make your query more readable.

    SELECT e.name, d.department_name FROM employees e INNER JOIN departments d ON e.department_id = d.id;

    This is similar to the first example but uses table aliases e and d for the employees and departments tables, respectively.

  4. Using WHERE Clause with Inner Join: You can also use the WHERE clause to further filter the joined result set.

    SELECT columns FROM table1 INNER JOIN table2 ON table1.column = table2.column WHERE condition;

    Example:

    SELECT employees.name, departments.department_name FROM employees INNER JOIN departments ON employees.department_id = departments.id WHERE departments.department_name = 'IT';

    This retrieves the name of employees along with their corresponding department names, but only for employees in the IT department.

Performing inner joins in MySQL allows you to combine data from multiple tables based on related columns, enabling you to retrieve comprehensive information for analysis or reporting.

Using aliases for table names

Using aliases for table names in MySQL can make your SQL queries more concise and readable. Here's how you can use aliases with examples:

  1. Basic Syntax with Aliases: You can assign an alias to a table name using the AS keyword.

    SELECT alias.column FROM tablename AS alias;

    Example:

    SELECT e.name, d.department_name FROM employees AS e INNER JOIN departments AS d ON e.department_id = d.id;

    This retrieves the name of employees along with their corresponding department names, using aliases e for the employees table and d for the departments table.

  2. Using Table Aliases in Joins: You can use table aliases to simplify join conditions.

    SELECT alias1.column1, alias2.column2 FROM tablename1 AS alias1 INNER JOIN tablename2 AS alias2 ON alias1.key = alias2.key;

    Example:

    SELECT o.order_id, c.customer_name FROM orders AS o INNER JOIN customers AS c ON o.customer_id = c.customer_id;

    This retrieves the order ID and customer name by joining the orders table with the customers table using aliases o and c, respectively.

  3. Using Aliases for Self-Joins: Aliases are useful for self-joins, where a table is joined with itself.

    SELECT alias1.column1, alias2.column2 FROM tablename AS alias1 INNER JOIN tablename AS alias2 ON alias1.key = alias2.foreign_key;

    Example:

    SELECT e1.name AS employee_name, e2.name AS manager_name FROM employees AS e1 INNER JOIN employees AS e2 ON e1.manager_id = e2.employee_id;

    This retrieves the name of each employee and their corresponding manager's name by joining the employees table with itself using aliases e1 and e2.

Using aliases for table names in MySQL improves the readability of your queries, especially in complex queries involving multiple tables or self-joins. It also reduces the amount of typing required and can make your queries more efficient to write and maintain.

Performing outer joins (LEFT JOIN, RIGHT JOIN, FULL OUTER JOIN)

Performing outer joins in MySQL allows you to retrieve rows from one or more tables even if there is no corresponding match in the other table. MySQL supports three types of outer joins: LEFT JOIN, RIGHT JOIN, and FULL OUTER JOIN. Here's how you can perform outer joins with examples:

  1. LEFT JOIN: Retrieves all rows from the left table and the matched rows from the right table. If there is no match, NULL values are returned for columns from the right table.

    SELECT columns FROM table1 LEFT JOIN table2 ON table1.column = table2.column;

    Example:

    SELECT customers.customer_id, orders.order_id FROM customers LEFT JOIN orders ON customers.customer_id = orders.customer_id;

    This retrieves the customer IDs along with their corresponding order IDs. If a customer has no orders, NULL values will be returned for the order ID.

  2. RIGHT JOIN: Retrieves all rows from the right table and the matched rows from the left table. If there is no match, NULL values are returned for columns from the left table.

    SELECT columns FROM table1 RIGHT JOIN table2 ON table1.column = table2.column;

    Example:

    SELECT customers.customer_id, orders.order_id FROM customers RIGHT JOIN orders ON customers.customer_id = orders.customer_id;

    This retrieves the order IDs along with their corresponding customer IDs. If an order has no customer, NULL values will be returned for the customer ID.

  3. FULL OUTER JOIN: Retrieves all rows from both tables. If there is no match, NULL values are returned for columns from the other table.

    MySQL does not directly support FULL OUTER JOIN syntax, but you can achieve the same result using a combination of LEFT JOIN and RIGHT JOIN with UNION DISTINCT.

    SELECT columns FROM table1 LEFT JOIN table2 ON table1.column = table2.column UNION SELECT columns FROM table1 RIGHT JOIN table2 ON table1.column = table2.column;

    Example:

    SELECT customers.customer_id, orders.order_id FROM customers LEFT JOIN orders ON customers.customer_id = orders.customer_id UNION SELECT customers.customer_id, orders.order_id FROM customers RIGHT JOIN orders ON customers.customer_id = orders.customer_id;

    This retrieves all customer IDs and order IDs from both tables. If there is no match, NULL values will be returned for the respective columns.

Performing outer joins in MySQL allows you to retrieve data from related tables even when there are unmatched rows, providing flexibility in your queries and ensuring that no data is omitted unintentionally.


12.7 Subqueries

Writing subqueries within SELECT, FROM, WHERE, and HAVING clauses

Subqueries in MySQL are queries nested within another query. They can be used in various parts of a SQL statement, including the SELECT, FROM, WHERE, and HAVING clauses. Here's how you can write subqueries in each clause with examples:

  1. Subqueries in SELECT Clause: You can use a subquery to return a single value or a set of values that is treated as a column in the outer query's result set.

    SELECT column1, (SELECT aggregate_function(column2) FROM tablename) AS subquery_result FROM tablename;

    Example:

    SELECT department_id, (SELECT COUNT(*) FROM employees WHERE department_id = departments.id) AS num_employees FROM departments;

    This retrieves the department ID along with the number of employees in each department using a subquery in the SELECT clause.

  2. Subqueries in FROM Clause (Derived Tables): You can use a subquery to create a derived table within the FROM clause, which can then be used as a regular table in the outer query.

    SELECT * FROM (SELECT column1, aggregate_function(column2) FROM tablename) AS derived_table;

    Example:

    SELECT * FROM (SELECT department_id, COUNT(*) AS num_employees FROM employees GROUP BY department_id) AS department_summary;

    This creates a derived table department_summary containing the department ID and the number of employees in each department, which can then be used in the outer query.

  3. Subqueries in WHERE Clause: You can use a subquery in the WHERE clause to filter rows based on the result of the subquery.

    SELECT columns FROM tablename WHERE column1 = (SELECT column2 FROM tablename WHERE condition);

    Example:

    SELECT * FROM employees WHERE department_id = (SELECT id FROM departments WHERE department_name = 'IT');

    This retrieves all employees who belong to the IT department using a subquery in the WHERE clause.

  4. Subqueries in HAVING Clause: You can use a subquery in the HAVING clause to filter groups based on the result of the subquery.

    SELECT column1, aggregate_function(column2) FROM tablename GROUP BY column1 HAVING aggregate_function(column2) = (SELECT aggregate_function(column3) FROM tablename WHERE condition);

    Example:

    SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id HAVING AVG(salary) > (SELECT AVG(salary) FROM employees);

    This retrieves the department IDs along with their average salary, filtering out departments where the average salary is higher than the overall average salary of all employees.

Subqueries in MySQL provide a powerful way to perform complex operations and enable you to write more flexible and expressive SQL queries. They can be used to retrieve data, create derived tables, filter rows, and filter groups based on the results of inner queries.

Correlated vs. non-correlated subqueries

In MySQL, subqueries can be classified as correlated or non-correlated based on their relationship with the outer query. Here's a breakdown of both types along with examples:

  1. Non-Correlated Subqueries: Non-correlated subqueries are independent of the outer query and can be evaluated separately. They are executed only once and their result is used in the outer query.

    SELECT column1 FROM tablename WHERE column2 = (SELECT aggregate_function(column3) FROM tablename WHERE condition);

    Example:

    SELECT department_name FROM departments WHERE id IN (SELECT department_id FROM employees WHERE salary > 50000);

    This retrieves department names where at least one employee has a salary greater than $50,000. The subquery (SELECT department_id FROM employees WHERE salary > 50000) is non-correlated because it doesn't reference any columns from the outer query.

  2. Correlated Subqueries: Correlated subqueries are dependent on the outer query. They are executed once for each row in the outer query and their execution depends on the values of the outer query.

    SELECT column1 FROM tablename AS outer_table WHERE condition = (SELECT aggregate_function(column2) FROM tablename AS inner_table WHERE inner_table.column3 = outer_table.column4);

    Example:

    SELECT department_name FROM departments AS d WHERE (SELECT COUNT(*) FROM employees AS e WHERE e.department_id = d.id) > 10;

    This retrieves department names where the number of employees in each department is greater than 10. The subquery (SELECT COUNT(*) FROM employees AS e WHERE e.department_id = d.id) is correlated because it references the id column from the outer query (d.id).

Correlated subqueries are often slower than non-correlated subqueries because they need to be executed multiple times, once for each row in the outer query. However, they are essential when you need to perform calculations or filtering based on values from the outer query. Non-correlated subqueries are more efficient but may not be suitable for all scenarios.

Using subqueries for filtering and aggregation

Using subqueries for filtering and aggregation in MySQL allows you to perform complex queries by leveraging the results of inner queries within the outer query. Here are examples demonstrating how to use subqueries for filtering and aggregation:

  1. Using Subqueries for Filtering: You can use subqueries in the WHERE clause to filter rows based on the result of an inner query.

    SELECT columns FROM tablename WHERE column1 IN (SELECT column2 FROM othertable WHERE condition);

    Example:

    SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE country = 'USA');

    This retrieves all orders placed by customers from the USA.

  2. Using Subqueries for Aggregation: You can use subqueries to perform aggregation within the outer query, allowing you to calculate summary statistics or filter groups based on aggregate values.

    SELECT column1, (SELECT aggregate_function(column2) FROM tablename WHERE condition) AS aggregate_value FROM tablename;

    Example:

    SELECT department_name, (SELECT COUNT(*) FROM employees WHERE department_id = departments.id) AS num_employees FROM departments;

    This retrieves department names along with the number of employees in each department.

  3. Combining Subqueries for Filtering and Aggregation: You can combine subqueries for both filtering and aggregation to perform more complex analyses.

    SELECT column1, (SELECT aggregate_function(column2) FROM tablename WHERE condition) AS aggregate_value FROM tablename WHERE column1 IN (SELECT column2 FROM othertable WHERE condition);

    Example:

    SELECT department_name, (SELECT AVG(salary) FROM employees WHERE department_id = departments.id) AS avg_salary FROM departments WHERE id IN (SELECT department_id FROM employees WHERE age > 30);

    This retrieves department names along with the average salary for departments with at least one employee older than 30.

Subqueries for filtering and aggregation in MySQL provide powerful capabilities for analyzing data and deriving insights from your database. They allow you to perform complex calculations and filtering operations within a single SQL query, making them a valuable tool for data analysis and reporting.


12.8 Set Operations

Combining query results with UNION, INTERSECT, and EXCEPT

In MySQL, you can combine query results from multiple SELECT statements using UNION, INTERSECT, and EXCEPT (which MySQL supports through the use of the UNION, INTERSECT, and EXCEPT operators respectively). Here's how you can use these operators with examples:

  1. UNION Operator: The UNION operator is used to combine the results of two or more SELECT statements into a single result set. It removes duplicate rows by default.

    SELECT columns FROM table1 UNION SELECT columns FROM table2;

    Example:

    SELECT employee_id, employee_name FROM department1 UNION SELECT employee_id, employee_name FROM department2;

    This retrieves all employee IDs and names from both department1 and department2, removing any duplicates.

  2. UNION ALL Operator: The UNION ALL operator is similar to UNION, but it retains all rows from the result sets, including duplicates.

    SELECT columns FROM table1 UNION ALL SELECT columns FROM table2;

    Example:

    SELECT employee_id, employee_name FROM department1 UNION ALL SELECT employee_id, employee_name FROM department2;

    This retrieves all employee IDs and names from both department1 and department2, including duplicates.

  3. INTERSECT Operator: The INTERSECT operator is used to return the common rows between the result sets of two SELECT statements. MySQL doesn't support the INTERSECT operator directly, but you can achieve the same result using INNER JOIN or EXISTS.

    SELECT columns FROM table1 INNER JOIN table2 ON condition;

    Example:

    SELECT employee_id, employee_name FROM department1 INNER JOIN department2 ON department1.employee_id = department2.employee_id;

    This retrieves the employee IDs and names that exist in both department1 and department2.

  4. EXCEPT Operator: The EXCEPT operator is used to return the rows from the first SELECT statement that are not present in the result set of the second SELECT statement. MySQL doesn't support the EXCEPT operator directly, but you can achieve the same result using LEFT JOIN or NOT EXISTS.

    SELECT columns FROM table1 LEFT JOIN table2 ON condition WHERE table2.column IS NULL;

    Example:

    SELECT employee_id, employee_name FROM department1 LEFT JOIN department2 ON department1.employee_id = department2.employee_id WHERE department2.employee_id IS NULL;

    This retrieves the employee IDs and names that exist in department1 but not in department2.

Combining query results with UNION, INTERSECT, and EXCEPT operators in MySQL allows you to perform set operations on multiple result sets, enabling you to analyze data and derive insights efficiently.

Understanding set operations and their usage

Set operations in MySQL allow you to perform operations such as union, intersection, and difference on the result sets of multiple queries. MySQL provides several operators and functions to perform set operations. Here's a brief overview of set operations and their usage in MySQL with examples:

  1. UNION:

    • The UNION operator combines the results of two or more SELECT statements into a single result set, removing duplicate rows by default.
    • You can use UNION ALL to retain duplicate rows.
    SELECT column1 FROM table1 UNION SELECT column1 FROM table2;

    Example:

    SELECT employee_id FROM department1 UNION SELECT employee_id FROM department2;
  2. INTERSECT:

    • The INTERSECT operator returns the common rows between the result sets of two SELECT statements. However, MySQL does not directly support the INTERSECT operator.
    • You can achieve the same result using INNER JOIN or EXISTS.

    Example with INNER JOIN:

    SELECT column1 FROM table1 INNER JOIN table2 ON table1.column1 = table2.column1;

    Example with EXISTS:

    SELECT column1 FROM table1 WHERE EXISTS ( SELECT 1 FROM table2 WHERE table1.column1 = table2.column1 );
  3. EXCEPT (Difference):

    • The EXCEPT operator returns the rows from the first SELECT statement that are not present in the result set of the second SELECT statement. MySQL does not directly support the EXCEPT operator.
    • You can achieve the same result using LEFT JOIN or NOT EXISTS.

    Example with LEFT JOIN:

    SELECT column1 FROM table1 LEFT JOIN table2 ON table1.column1 = table2.column1 WHERE table2.column1 IS NULL;

    Example with NOT EXISTS:

    SELECT column1 FROM table1 WHERE NOT EXISTS ( SELECT 1 FROM table2 WHERE table1.column1 = table2.column1 );

Set operations in MySQL are useful for combining, comparing, and analyzing data from multiple tables or queries. They provide flexibility in querying and deriving insights from your database. While MySQL does not support INTERSECT and EXCEPT operators directly, you can achieve similar functionality using other SQL constructs like INNER JOIN, EXISTS, LEFT JOIN, and NOT EXISTS.


12.9 Conditional Expressions

Using CASE expressions for conditional logic

CASE expressions in MySQL allow you to perform conditional logic within a SQL query. They are useful for evaluating conditions and returning different values based on those conditions. Here's how you can use CASE expressions with examples:

  1. Simple CASE Expression: You can use a simple CASE expression to compare an expression to a set of values and return a result based on the first matching value.

    CASE expression WHEN value1 THEN result1 WHEN value2 THEN result2 ... ELSE default_result END

    Example:

    SELECT employee_id, CASE department_id WHEN 1 THEN 'IT' WHEN 2 THEN 'HR' ELSE 'Other' END AS department_name FROM employees;

    This returns the department name for each employee based on their department ID.

  2. Searched CASE Expression: You can use a searched CASE expression to evaluate multiple conditions and return a result based on the first condition that evaluates to true.

    CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... ELSE default_result END

    Example:

    SELECT employee_id, CASE WHEN age < 30 THEN 'Young' WHEN age >= 30 AND age < 50 THEN 'Middle-aged' ELSE 'Senior' END AS age_group FROM employees;

    This categorizes employees into different age groups based on their age.

  3. Using CASE in UPDATE Statements: You can also use CASE expressions in UPDATE statements to conditionally update values in a table.

    UPDATE tablename SET column = CASE WHEN condition1 THEN value1 WHEN condition2 THEN value2 ... ELSE column END WHERE condition;

    Example:

    UPDATE employees SET salary = CASE WHEN department_id = 1 THEN salary * 1.1 WHEN department_id = 2 THEN salary * 1.05 ELSE salary END WHERE age > 30;

    This increases the salary of employees in the IT department by 10% and in the HR department by 5% if they are older than 30.

CASE expressions in MySQL provide a powerful way to perform conditional logic within SQL queries, allowing you to customize query results based on specific conditions. They are commonly used in SELECT, UPDATE, and other SQL statements to handle different scenarios and derive meaningful insights from your data.

Handling NULL values with CASE

Handling NULL values with CASE expressions in MySQL allows you to perform conditional logic based on whether a value is NULL or not. Here's how you can use CASE expressions to handle NULL values with examples:

  1. Using CASE to Check for NULL: You can use a CASE expression to check if a column value is NULL and return a specific result.

    SELECT column1, CASE WHEN column2 IS NULL THEN 'Null Value' ELSE 'Not Null Value' END AS null_check FROM tablename;

    Example:

    SELECT employee_id, CASE WHEN manager_id IS NULL THEN 'No Manager' ELSE 'Has Manager' END AS manager_status FROM employees;

    This returns whether each employee has a manager or not based on the manager_id column.

  2. Using CASE to Handle NULL Values in Calculations: You can use CASE expressions to handle NULL values in calculations by providing a default value when the column is NULL.

    SELECT column1, CASE WHEN column2 IS NULL THEN default_value ELSE column2 END AS non_null_column FROM tablename;

    Example:

    SELECT employee_id, CASE WHEN salary IS NULL THEN 0 ELSE salary END AS actual_salary FROM employees;

    This returns the actual salary for each employee, replacing NULL values with 0.

  3. Using CASE to Coalesce NULL Values: You can use CASE expressions along with the COALESCE function to replace NULL values with another value.

    SELECT column1, CASE WHEN column2 IS NULL THEN coalesce_value ELSE column2 END AS non_null_column FROM tablename;

    Example:

    SELECT employee_id, CASE WHEN commission IS NULL THEN 0.00 ELSE commission END AS actual_commission FROM employees;

    This returns the actual commission for each employee, replacing NULL values with 0.00.

CASE expressions in MySQL provide a flexible way to handle NULL values in SQL queries, allowing you to customize the behavior based on your requirements. Whether you need to check for NULL values, handle them in calculations, or replace them with default values, CASE expressions offer a versatile solution for dealing with NULL values in your database.

Conditional aggregation with CASE and aggregate functions

Conditional aggregation with CASE and aggregate functions in MySQL allows you to perform aggregate operations based on specific conditions. You can use CASE expressions within aggregate functions to selectively include or exclude rows in the calculation. Here's how you can use conditional aggregation with examples:

  1. Using CASE with SUM: You can use a CASE expression within the SUM function to conditionally sum values based on specific conditions.

    SELECT department_id, SUM(CASE WHEN condition THEN column1 ELSE 0 END) AS conditional_sum FROM tablename GROUP BY department_id;

    Example:

    SELECT department_id, SUM(CASE WHEN salary > 50000 THEN 1 ELSE 0 END) AS high_salary_count FROM employees GROUP BY department_id;

    This calculates the count of employees with a salary greater than $50,000 for each department.

  2. Using CASE with AVG: You can use a CASE expression within the AVG function to conditionally calculate the average based on specific conditions.

    SELECT department_id, AVG(CASE WHEN condition THEN column1 ELSE NULL END) AS conditional_avg FROM tablename GROUP BY department_id;

    Example:

    SELECT department_id, AVG(CASE WHEN age < 30 THEN salary ELSE NULL END) AS avg_salary_young FROM employees GROUP BY department_id;

    This calculates the average salary for employees younger than 30 for each department.

  3. Using CASE with COUNT: You can use a CASE expression within the COUNT function to conditionally count rows based on specific conditions.

    SELECT department_id, COUNT(CASE WHEN condition THEN column1 END) AS conditional_count FROM tablename GROUP BY department_id;

    Example:

    SELECT department_id, COUNT(CASE WHEN gender = 'Female' THEN 1 END) AS female_count FROM employees GROUP BY department_id;

    This calculates the count of female employees for each department.

Conditional aggregation with CASE and aggregate functions in MySQL allows you to perform complex calculations based on specific conditions. It's particularly useful when you need to calculate aggregate values selectively depending on various criteria, providing flexibility and control over your query results.


12.10 String Functions

Common string functions (e.g., CONCAT, SUBSTRING, UPPER, LOWER, REPLACE)

In MySQL, there are various string functions available that allow you to manipulate and work with strings in your queries. Here are some common string functions along with examples:

  1. CONCAT:

    • Concatenates two or more strings together.
    SELECT CONCAT(string1, string2) AS concatenated_string;

    Example:

    SELECT CONCAT('Hello ', 'World') AS concatenated_string;

    Output: "Hello World"

  2. SUBSTRING:

    • Extracts a substring from a string.
    SELECT SUBSTRING(string, start_position, length) AS substring;

    Example:

    SELECT SUBSTRING('Hello World', 1, 5) AS substring;

    Output: "Hello"

  3. UPPER:

    • Converts a string to uppercase.
    SELECT UPPER(string) AS uppercase_string;

    Example:

    SELECT UPPER('hello') AS uppercase_string;

    Output: "HELLO"

  4. LOWER:

    • Converts a string to lowercase.
    SELECT LOWER(string) AS lowercase_string;

    Example:

    SELECT LOWER('WORLD') AS lowercase_string;

    Output: "world"

  5. REPLACE:

    • Replaces occurrences of a specified string within another string.
    SELECT REPLACE(string, search_string, replacement_string) AS replaced_string;

    Example:

    SELECT REPLACE('Hello World', 'World', 'Universe') AS replaced_string;

    Output: "Hello Universe"

  6. LENGTH:

    • Returns the length of a string.
    SELECT LENGTH(string) AS string_length;

    Example:

    SELECT LENGTH('Hello World') AS string_length;

    Output: 11 (including spaces)

  7. TRIM:

    • Removes leading and trailing spaces from a string.
    SELECT TRIM(string) AS trimmed_string;

    Example:

    SELECT TRIM(' Hello World ') AS trimmed_string;

    Output: "Hello World"

These are some of the common string functions available in MySQL. They can be useful for various tasks such as data cleaning, formatting, and manipulation within your SQL queries.

Manipulating string data in SQL queries

Manipulating string data in SQL queries in MySQL involves using various string functions and operators to perform tasks such as concatenation, substring extraction, case conversion, and string replacement. Here's how you can manipulate string data in MySQL with examples:

  1. Concatenating Strings: You can concatenate strings using the CONCAT function or the concatenation operator (||).

    -- Using CONCAT function SELECT CONCAT('Hello', ' ', 'World') AS concatenated_string; -- Using concatenation operator SELECT 'Hello' || ' ' || 'World' AS concatenated_string;
  2. Extracting Substrings: You can extract substrings from a string using the SUBSTRING function.

    SELECT SUBSTRING('Hello World', 1, 5) AS substring;
  3. Converting Case: You can convert the case of a string using the UPPER and LOWER functions.

    SELECT UPPER('hello') AS uppercase_string; SELECT LOWER('WORLD') AS lowercase_string;
  4. Replacing Substrings: You can replace occurrences of a substring within a string using the REPLACE function.

    SELECT REPLACE('Hello World', 'World', 'Universe') AS replaced_string;
  5. Getting String Length: You can get the length of a string using the LENGTH function.

    SELECT LENGTH('Hello World') AS string_length;
  6. Trimming Spaces: You can remove leading and trailing spaces from a string using the TRIM function.

    SELECT TRIM(' Hello World ') AS trimmed_string;
  7. Padding Strings: You can pad strings with spaces or other characters using the LPAD and RPAD functions.

    SELECT LPAD('Hello', 10, '*') AS padded_string; SELECT RPAD('World', 10, '-') AS padded_string;
  8. Reversing Strings: You can reverse the characters in a string using the REVERSE function.

    SELECT REVERSE('Hello World') AS reversed_string;

These are some of the common string manipulation techniques you can use in MySQL queries. They allow you to transform and manipulate string data to meet your specific requirements within SQL queries.


12.11 Date and Time Functions

Common date and time functions (e.g., DATEADD, DATEDIFF, GETDATE, CONVERT)

In MySQL, there are various date and time functions available that allow you to work with date and time data in your queries. Here are some common date and time functions along with examples:

  1. NOW:

    • Returns the current date and time.
    SELECT NOW() AS current_datetime;
  2. CURDATE:

    • Returns the current date.
    SELECT CURDATE() AS current_date;
  3. CURTIME:

    • Returns the current time.
    SELECT CURTIME() AS current_time;
  4. DATE_ADD:

    • Adds a specified interval to a date.
    SELECT DATE_ADD('2022-01-01', INTERVAL 1 DAY) AS next_day;
  5. DATE_SUB:

    • Subtracts a specified interval from a date.
    SELECT DATE_SUB('2022-01-01', INTERVAL 1 MONTH) AS previous_month;
  6. DATEDIFF:

    • Calculates the difference between two dates in days.
    SELECT DATEDIFF('2022-01-01', '2022-02-01') AS days_difference;
  7. DATE_FORMAT:

    • Formats a date according to a specified format.
    SELECT DATE_FORMAT(NOW(), '%Y-%m-%d') AS formatted_date;
  8. DAYNAME:

    • Returns the name of the weekday for a given date.
    SELECT DAYNAME('2022-01-01') AS day_name;
  9. MONTHNAME:

    • Returns the name of the month for a given date.
    SELECT MONTHNAME('2022-01-01') AS month_name;
  10. YEAR:

    • Returns the year part of a date.
    SELECT YEAR('2022-01-01') AS year;
  11. TIME_FORMAT:

    • Formats a time according to a specified format.
    SELECT TIME_FORMAT(NOW(), '%H:%i:%s') AS formatted_time;
  12. TIMESTAMPDIFF:

    • Calculates the difference between two timestamps in a specified unit.
    SELECT TIMESTAMPDIFF(MINUTE, '2022-01-01 12:00:00', NOW()) AS minutes_difference;

These are some of the common date and time functions available in MySQL. They can be useful for various tasks such as date arithmetic, date formatting, and extracting date parts within your SQL queries.

Formatting date and time values

In MySQL, you can format date and time values using the DATE_FORMAT function. This function allows you to specify a format string to control how the date and time values are displayed. Here's how you can format date and time values in MySQL with examples:

  1. Formatting Date Values:

    SELECT DATE_FORMAT(date_column, 'format_string') AS formatted_date;

    Example:

    SELECT DATE_FORMAT('2022-04-30', '%Y-%m-%d') AS formatted_date;

    Output: "2022-04-30"

  2. Formatting Time Values:

    SELECT DATE_FORMAT(time_column, 'format_string') AS formatted_time;

    Example:

    SELECT DATE_FORMAT('12:30:45', '%H:%i:%s') AS formatted_time;

    Output: "12:30:45"

  3. Formatting DateTime Values:

    SELECT DATE_FORMAT(datetime_column, 'format_string') AS formatted_datetime;

    Example:

    SELECT DATE_FORMAT('2022-04-30 12:30:45', '%Y-%m-%d %H:%i:%s') AS formatted_datetime;

    Output: "2022-04-30 12:30:45"

  4. Using Format Specifiers:

    • %Y: Year with century (e.g., 2022)
    • %y: Year without century (e.g., 22)
    • %m: Month (01..12)
    • %d: Day of the month (01..31)
    • %H: Hour (00..23)
    • %h: Hour (01..12)
    • %i: Minutes (00..59)
    • %s: Seconds (00..59)
    • %p: AM or PM

    Example:

    SELECT DATE_FORMAT('2022-04-30 12:30:45', '%Y-%m-%d %h:%i:%s %p') AS formatted_datetime;

    Output: "2022-04-30 12:30:45 PM"

You can customize the format string as needed to display date and time values in the desired format. The DATE_FORMAT function provides flexibility in formatting date and time values according to your specific requirements within MySQL queries.


12.12 Advanced SQL Techniques

Using window functions for advanced analytics (e.g., ROW_NUMBER, RANK, DENSE_RANK)

Window functions in MySQL allow you to perform advanced analytics and calculations across a set of rows without grouping the result set. Common window functions include ROW_NUMBER, RANK, and DENSE_RANK. Here's how you can use these window functions in MySQL with examples:

  1. ROW_NUMBER:

    • Assigns a unique sequential integer to each row within a partition of a result set.
    SELECT column1, column2, ROW_NUMBER() OVER (ORDER BY column1) AS row_number FROM tablename;

    Example:

    SELECT employee_id, employee_name, ROW_NUMBER() OVER (ORDER BY employee_id) AS row_number FROM employees;
  2. RANK:

    • Assigns a unique rank to each distinct row value within a partition of a result set. If two or more rows have the same value, they receive the same rank, and the next rank is skipped.
    SELECT column1, column2, RANK() OVER (ORDER BY column1) AS rank FROM tablename;

    Example:

    SELECT department_id, AVG(salary) AS average_salary, RANK() OVER (ORDER BY AVG(salary) DESC) AS rank FROM employees GROUP BY department_id;
  3. DENSE_RANK:

    • Assigns a unique rank to each distinct row value within a partition of a result set. If two or more rows have the same value, they receive the same rank, and the next rank is not skipped.
    SELECT column1, column2, DENSE_RANK() OVER (ORDER BY column1) AS dense_rank FROM tablename;

    Example:

    SELECT department_id, AVG(salary) AS average_salary, DENSE_RANK() OVER (ORDER BY AVG(salary) DESC) AS dense_rank FROM employees GROUP BY department_id;

Window functions allow you to perform complex calculations and analytics on your data set without the need for subqueries or joins. They are particularly useful for ranking, aggregating, and analyzing data in SQL queries.

Recursive queries with Common Table Expressions (CTEs)

In MySQL, you can use Common Table Expressions (CTEs) to write recursive queries, allowing you to perform operations that involve hierarchical or recursive data structures. Here's how you can use CTEs to write recursive queries in MySQL with an example:

  1. Syntax for Recursive CTE:

    WITH RECURSIVE cte_name AS ( -- Anchor member: Initial query result SELECT ... UNION ALL -- Recursive member: Query to be executed repeatedly SELECT ... FROM cte_name WHERE ... ) SELECT * FROM cte_name;
  2. Example of Recursive CTE:

    Suppose you have a table employees with columns employee_id and manager_id, where manager_id references employee_id of another employee who is the manager of the current employee.

    WITH RECURSIVE EmployeeHierarchy AS ( -- Anchor member: Employees who do not have a manager SELECT employee_id, employee_name, manager_id, 0 AS depth FROM employees WHERE manager_id IS NULL UNION ALL -- Recursive member: Employees who report to the previously selected employees SELECT e.employee_id, e.employee_name, e.manager_id, eh.depth + 1 FROM employees e JOIN EmployeeHierarchy eh ON e.manager_id = eh.employee_id ) SELECT * FROM EmployeeHierarchy;

    In this example:

    • The anchor member selects employees who do not have a manager (those with a NULL manager_id).
    • The recursive member selects employees who report to the employees selected in the previous iteration by joining with the CTE itself (EmployeeHierarchy).
    • The recursion continues until no more rows are returned by the recursive member.

    This query retrieves the entire hierarchy of employees, including their depth in the hierarchy (level).

Recursive CTEs in MySQL provide a powerful mechanism for querying hierarchical data structures efficiently. They allow you to express complex relationships and traversals in a concise and readable manner.

Dynamic SQL and parameterized queries

Dynamic SQL and parameterized queries in MySQL enable you to construct SQL statements dynamically at runtime and execute them with parameters. Dynamic SQL is particularly useful when you need to create SQL statements based on varying conditions or inputs. Parameterized queries help prevent SQL injection attacks and improve performance by allowing MySQL to cache query execution plans. Here's how you can use dynamic SQL and parameterized queries in MySQL with examples:

  1. Dynamic SQL:

    SET @sql = CONCAT('SELECT * FROM employees WHERE department_id = ', @department_id); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

    In this example, @department_id is a variable containing the department ID value. We construct a SQL statement dynamically using CONCAT, prepare the statement with PREPARE, execute it with EXECUTE, and deallocate the prepared statement with DEALLOCATE.

  2. Parameterized Queries:

    PREPARE stmt FROM 'SELECT * FROM employees WHERE department_id = ?'; SET @department_id = 1; EXECUTE stmt USING @department_id; DEALLOCATE PREPARE stmt;

    In this example, we use a parameter placeholder ? in the SQL statement to indicate a parameterized query. We prepare the statement with PREPARE, set the value of the department ID parameter, execute the statement with EXECUTE using the USING clause, and deallocate the prepared statement.

Parameterized queries offer several benefits, including improved security, as they help prevent SQL injection attacks by separating SQL code from user input. Additionally, they can improve performance by allowing MySQL to reuse cached query execution plans for different parameter values. Dynamic SQL, on the other hand, provides flexibility in constructing SQL statements based on runtime conditions or variables. However, it's essential to ensure proper validation and sanitization of inputs when using dynamic SQL to avoid security vulnerabilities.


11. Database Design and Modeling
13. Data Definition Language (DDL)