SQL Cheatsheet
- Group by example
- Split a string into multiple columns
- Date and Time
- CREATE
- Functions
- Advance query examples
- Drop All Tables
- Making Queries Readable
- FAQ's
Group by example
select id, module_id, title from lessons
where id in (11, 13, 15, 22, 23, 24, 25, 26)
group by module_id;
11 7 Introduction
13 7 Quiz 1
15 7 Quiz 2
22 7 Learning Outcomes
23 8 Learning Outcomes
24 8 Introduction
25 9 Introduction
26 9 Learning Outcomes
-- Grouped by module_id
11 7 Introduction
23 8 Learning Outcomes
25 9 Introduction
Split a string into multiple columns
Splits a name into first and last name
UPDATE users
SET lastname = SUBSTRING_INDEX(name, ' ', -1),
firstname = SUBSTRING_INDEX(name, ' ', 1);
Date and Time
CURDATE()
Set current date UPDATE my_table
SET date_column = CURDATE();
CREATE
CREATE TABLE IF NOT EXISTS table_name (
column1 datatype,
....
);
Functions
REPLACE(str_or_field, find_string, replace_with)
SELECT title, REPLACE(title, 'Section', 'Module')
FROM chapters WHERE title LIKE '%Section%';
Select by the number of segments in a path
SELECT route_prefix
FROM pages
WHERE LENGTH(route_prefix) - LENGTH(REPLACE(route_prefix, '/', '')) + 1 = 2;
Explanation:
AND LENGTH(route) - LENGTH(REPLACE(route, '/', '')) + 1 = 2 filters the results further to only include rows where the number of segments in the route column is 2. This is done by counting the number of slashes in the route string and adding 1 to get the number of segments.
This will only work with the exact number of slashes
Advance query examples
id | type | title | courses | main_category_id | sub_category_id |
---|---|---|---|---|---|
1 | main | Main Category 1 | null | null | null |
2 | sub | Sub Category 1 | null | 1 | null |
3 | item | Item 1 | EP01 | 1 | 2 |
4 | item | Item 2 | 1 | 2 | |
5 | sub | Sub Category 2 | null | 1 | null |
6 | item | Item 3 | 1 | 5 | |
7 | item | Item 4 | 1 | 5 |
-- sub query or IN condition (1, 76, 89)
SELECT main_category_id
FROM exam_prep_outlines
WHERE AND courses LIKE '%EP04%';
-- laravel equivalent
$mainCategories = ExamPrepOutline::where('courses', 'like', "%$code%")
->groupBy('main_category_id')
->pluck('main_category_id');
SELECT * FROM exam_prep_outlines
WHERE (type = 'item' AND courses LIKE '%EP04%')
OR (type = 'sub' AND main_category_id IN (
SELECT main_category_id
FROM exam_prep_outlines
WHERE courses LIKE '%EP04%'
));
-- laravel equivalent
$courseOutline = ExamPrepOutline::where('courses', 'like', "%$code%")
->orWhere('type', 'sub')
->whereIn('main_category_id', $mainCategories)
->get();
Output table
id | type | title | courses | courses | main_cat_id | sub_cat_id |
---|---|---|---|---|---|---|
2 | sub | A | Infant | 1 | ||
3 | item | 1 | Feeding behaviours at different ages | EP04, EP12 | 1 | 2 |
5 | item | 3 | Infant anatomy and anatomical/oral challenges | EP04 | 1 | 2 |
9 | item | 7 | Normal infant behaviours | EP04 | 1 | 2 |
10 | item | 8 | Nutritional requirements - including preterm | EP04, EP10 | 1 | 2 |
12 | item | 10 | Skin tone, muscle tone, reflexes | EP04 | 1 | 2 |
15 | item | 13 | Stooling and voiding | EP04 | 1 | 2 |
16 | sub | B | Maternal | 1 | ||
85 | item | 9 | Breastfeeding dyad relationship | EP04, EP13 | 76 | |
90 | item | 1 | Effective milk transfer | EP04 | 89 | |
91 | item | 2 | First hour | EP04 | 89 | |
92 | item | 3 | Latching (attaching) | EP04 | 89 | |
93 | item | 4 | Managing supply | EP03, EP04 | 89 | |
94 | item | 5 | Milk expression | EP04. EP06 | 89 | |
95 | item | 6 | Position of the breastfeeding dyad (hands-off) | EP04 | 89 | |
97 | item | 8 | Skin-to-skin (kangaroo care) | EP04 | 89 |
Drop All Tables
This script first disables foreign key checks to avoid issues with foreign key constraints,
generates the DROP TABLE
statements, and then re-enables foreign key checks. Note that you need to
manually execute the generated DROP TABLE
statements after generating the initial script as shown
below.
SET FOREIGN_KEY_CHECKS = 0;
-- Generate DROP TABLE statements for all tables
SET @tables = NULL;
SELECT GROUP_CONCAT('`', table_name, '`') INTO @tables
FROM information_schema.tables
WHERE table_schema = (SELECT DATABASE());
-- Execute the DROP TABLE statements
SET @tables = CONCAT('DROP TABLE IF EXISTS ', @tables);
PREPARE stmt FROM @tables;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET FOREIGN_KEY_CHECKS = 1;
Making Queries Readable
To make queries more readable, you can use subqueries to break down the query into smaller parts. This can be useful when you have a complex query that is difficult to read.
For example, the following query uses a subquery to get the id
of a student's courses and then
uses that id
to get the lessons for those courses.
-- Subquery
WITH StudentCourses AS (
SELECT id FROM student_courses
WHERE user_id = 1
)
-- Main query
SELECT * FROM student_lessons
WHERE student_course_id IN (
SELECT id FROM StudentCourses
);
FAQ's
Does it make sense to add foreign keys in deep relationships?
When structuring database tables, is it better to add foreign keys for deep relationships or rely on queries to navigate between related tables?
For example:
- A user has many student courses
- A student course has many lessons
- A lesson has one answer
Should user_id
be included in each table?
- A student course belongs to one user
- A lesson belongs to one user
- A question belongs to one user
In most cases, adding user_id
to every table in a deep relationship is unnecessary. Use foreign
keys and queries to navigate between related tables.
Only add user_id
to deeper tables if direct access to user data is frequently needed for
performance. Otherwise, rely on the existing relationships.