├── Tables.xlsx ├── DB Requirements.docx ├── Entity Definitions & Relationships - ILS DB.pdf ├── README.md └── ILS_DB_code.sql /Tables.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thecraigd/SQL_School_Tutorial/HEAD/Tables.xlsx -------------------------------------------------------------------------------- /DB Requirements.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thecraigd/SQL_School_Tutorial/HEAD/DB Requirements.docx -------------------------------------------------------------------------------- /Entity Definitions & Relationships - ILS DB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thecraigd/SQL_School_Tutorial/HEAD/Entity Definitions & Relationships - ILS DB.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CraigDoesData][logo]][link] 2 | 3 | [logo]: https://www.craigdoesdata.de/img/logo/logo.png 4 | [link]: https://www.craigdoesdata.de/ 5 | 6 | 7 | # Building a Relational Database from scratch using MySQL 8 | ## Learn to create, update and interrogate your own fully-functional relational database using SQL with free open-source software 9 | Database building project to accompany these tutorials: 10 | - [Designing a Relational Database and Creating an Entity Relationship Diagram (SQL Part 1)](https://towardsdatascience.com/designing-a-relational-database-and-creating-an-entity-relationship-diagram-89c1c19320b2). 11 | - [Coding and Implementing a Relational Database using MySQL (SQL part 2)](https://towardsdatascience.com/coding-and-implementing-a-relational-database-using-mysql-d9bc69be90f5). 12 | - [Data Analysis in MySQL — Operators, Joins and More in Relational Databases (SQL part 3)](https://towardsdatascience.com/data-analysis-in-mysql-operators-joins-and-more-in-relational-databases-26c0a968e61e). 13 | 14 | 15 | 16 | #### Project status - Complete 17 | 18 | ## Introduction 19 | This repository contains the files to accompany the series of tutorials I wrote which cover designing, implementing and interrogating a relational database from scratch. The code to go with the tutorial is contained in [this .SQL file](https://github.com/thecraigd/SQL_School_Tutorial/blob/master/ILS_DB_code.sql). 20 | 21 | ### Methods used 22 | * Database Schema Planning 23 | * Entity Relationship Diagram Construction 24 | * Database Implementation 25 | * SQL Query creation, joins, nested queries, etc 26 | 27 | 28 | ### Technologies used 29 | * [MySQL Community Server](https://dev.mysql.com/downloads/mysql/) 30 | * [PopSQL](https://popsql.com/) 31 | * [Lucidchart](https://www.lucidchart.com/pages/) 32 | 33 | 34 | 35 | ### Data Sources 36 | 37 | Data was created to populate the database by me, [Craig Dickson](https://www.craigdoesdata.de). 38 | Some participant names were created using [Fake Name Generator](https://www.fakenamegenerator.com/). 39 | 40 | ### Getting started 41 | 42 | 1. Clone this repo (for help see this [tutorial](https://help.github.com/articles/cloning-a-repository/)). 43 | 2. Read the associated tutorials: 44 | - [Designing a Relational Database and Creating an Entity Relationship Diagram (SQL Part 1)](https://towardsdatascience.com/designing-a-relational-database-and-creating-an-entity-relationship-diagram-89c1c19320b2). 45 | - [Coding and Implementing a Relational Database using MySQL (SQL part 2)](https://towardsdatascience.com/coding-and-implementing-a-relational-database-using-mysql-d9bc69be90f5). 46 | - [Data Analysis in MySQL — Operators, Joins and More in Relational Databases (SQL part 3)](https://towardsdatascience.com/data-analysis-in-mysql-operators-joins-and-more-in-relational-databases-26c0a968e61e). 47 | 48 | 49 | ## Contact 50 | All feedback is warmly received. I can be contacted via my website [craigdoesdata.de](https://www.craigdoesdata.de/contact.html). 51 | -------------------------------------------------------------------------------- /ILS_DB_code.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Creating the tables -- 3 | 4 | CREATE TABLE teacher ( 5 | teacher_id INT PRIMARY KEY, 6 | first_name VARCHAR(40) NOT NULL, 7 | last_name VARCHAR(40) NOT NULL, 8 | language_1 VARCHAR(3) NOT NULL, 9 | language_2 VARCHAR(3), 10 | dob DATE, 11 | tax_id INT UNIQUE, 12 | phone_no VARCHAR(20) 13 | ); 14 | 15 | CREATE TABLE client ( 16 | client_id INT PRIMARY KEY, 17 | client_name VARCHAR(40) NOT NULL, 18 | address VARCHAR(60) NOT NULL, 19 | industry VARCHAR(20) 20 | ); 21 | 22 | CREATE TABLE participant ( 23 | participant_id INT PRIMARY KEY, 24 | first_name VARCHAR(40) NOT NULL, 25 | last_name VARCHAR(40) NOT NULL, 26 | phone_no VARCHAR(20), 27 | client INT 28 | ); 29 | 30 | CREATE TABLE course ( 31 | course_id INT PRIMARY KEY, 32 | course_name VARCHAR(40) NOT NULL, 33 | language VARCHAR(3) NOT NULL, 34 | level VARCHAR(2), 35 | course_length_weeks INT, 36 | start_date DATE, 37 | in_school BOOLEAN, 38 | teacher INT, 39 | client INT 40 | ); 41 | 42 | 43 | -- Altering the tables to establish the relationships via FOREIGN KEYs 44 | 45 | ALTER TABLE participant 46 | ADD FOREIGN KEY(client) 47 | REFERENCES client(client_id) 48 | ON DELETE SET NULL; 49 | 50 | ALTER TABLE course 51 | ADD FOREIGN KEY(teacher) 52 | REFERENCES teacher(teacher_id) 53 | ON DELETE SET NULL; 54 | 55 | ALTER TABLE course 56 | ADD FOREIGN KEY(client) 57 | REFERENCES client(client_id) 58 | ON DELETE SET NULL; 59 | 60 | 61 | 62 | CREATE TABLE takes_course ( 63 | participant_id INT, 64 | course_id INT, 65 | PRIMARY KEY(participant_id, course_id), 66 | FOREIGN KEY(participant_id) REFERENCES participant(participant_id) ON DELETE CASCADE, -- it makes no sense to keep this rtelation when a participant or course is no longer in the system, hence why CASCADE this time 67 | FOREIGN KEY(course_id) REFERENCES course(course_id) ON DELETE CASCADE 68 | ); 69 | 70 | 71 | 72 | /* 73 | -- If needed to quickly delete and re-build the tables: 74 | 75 | SET FOREIGN_KEY_CHECKS = 0; 76 | 77 | DROP TABLE client; 78 | DROP TABLE course; 79 | DROP TABLE participant; 80 | DROP TABLE takes_course; 81 | DROP TABLE teacher; 82 | 83 | SET FOREIGN_KEY_CHECKS = 1; 84 | 85 | */ 86 | 87 | -- Populating the tables 88 | 89 | INSERT INTO teacher VALUES 90 | (1, 'James', 'Smith', 'ENG', NULL, '1985-04-20', 12345, '+491774553676'), 91 | (2, 'Stefanie', 'Martin', 'FRA', NULL, '1970-02-17', 23456, '+491234567890'), 92 | (3, 'Steve', 'Wang', 'MAN', 'ENG', '1990-11-12', 34567, '+447840921333'), 93 | (4, 'Friederike', 'Müller-Rossi', 'DEU', 'ITA', '1987-07-07', 45678, '+492345678901'), 94 | (5, 'Isobel', 'Ivanova', 'RUS', 'ENG', '1963-05-30', 56789, '+491772635467'), 95 | (6, 'Niamh', 'Murphy', 'ENG', 'IRI', '1995-09-08', 67890, '+491231231232'); 96 | 97 | 98 | INSERT INTO client VALUES 99 | (101, 'Big Business Federation', '123 Falschungstraße, 10999 Berlin', 'NGO'), 100 | (102, 'eCommerce GmbH', '27 Ersatz Allee, 10317 Berlin', 'Retail'), 101 | (103, 'AutoMaker AG', '20 Künstlichstraße, 10023 Berlin', 'Auto'), 102 | (104, 'Banko Bank', '12 Betrugstraße, 12345 Berlin', 'Banking'), 103 | (105, 'WeMoveIt GmbH', '138 Arglistweg, 10065 Berlin', 'Logistics'); 104 | 105 | 106 | INSERT INTO participant VALUES 107 | (101, 'Marina', 'Berg','491635558182', 101), 108 | (102, 'Andrea', 'Duerr', '49159555740', 101), 109 | (103, 'Philipp', 'Probst', '49155555692', 102), 110 | (104, 'René', 'Brandt', '4916355546', 102), 111 | (105, 'Susanne', 'Shuster', '49155555779', 102), 112 | (106, 'Christian', 'Schreiner', '49162555375', 101), 113 | (107, 'Harry', 'Kim', '49177555633', 101), 114 | (108, 'Jan', 'Nowak', '49151555824', 101), 115 | (109, 'Pablo', 'Garcia', '49162555176', 101), 116 | (110, 'Melanie', 'Dreschler', '49151555527', 103), 117 | (111, 'Dieter', 'Durr', '49178555311', 103), 118 | (112, 'Max', 'Mustermann', '49152555195', 104), 119 | (113, 'Maxine', 'Mustermann', '49177555355', 104), 120 | (114, 'Heiko', 'Fleischer', '49155555581', 105); 121 | 122 | 123 | INSERT INTO course VALUES 124 | (12, 'English for Logistics', 'ENG', 'A1', 10, '2020-02-01', TRUE, 1, 105), 125 | (13, 'Beginner English', 'ENG', 'A2', 40, '2019-11-12', FALSE, 6, 101), 126 | (14, 'Intermediate English', 'ENG', 'B2', 40, '2019-11-12', FALSE, 6, 101), 127 | (15, 'Advanced English', 'ENG', 'C1', 40, '2019-11-12', FALSE, 6, 101), 128 | (16, 'Mandarin für Autoindustrie', 'MAN', 'B1', 15, '2020-01-15', TRUE, 3, 103), 129 | (17, 'Français intermédiaire', 'FRA', 'B1', 18, '2020-04-03', FALSE, 2, 101), 130 | (18, 'Deutsch für Anfänger', 'DEU', 'A2', 8, '2020-02-14', TRUE, 4, 102), 131 | (19, 'Intermediate English', 'ENG', 'B2', 10, '2020-03-29', FALSE, 1, 104), 132 | (20, 'Fortgeschrittenes Russisch', 'RUS', 'C1', 4, '2020-04-08', FALSE, 5, 103); 133 | 134 | 135 | INSERT INTO takes_course VALUES 136 | (101, 15), 137 | (101, 17), 138 | (102, 17), 139 | (103, 18), 140 | (104, 18), 141 | (105, 18), 142 | (106, 13), 143 | (107, 13), 144 | (108, 13), 145 | (109, 14), 146 | (109, 15), 147 | (110, 16), 148 | (110, 20), 149 | (111, 16), 150 | (114, 12), 151 | (112, 19), 152 | (113, 19); 153 | 154 | 155 | -- --------------------------------------------------------------------------------------------------------- 156 | 157 | 158 | -- Now for some fun! It's query-time. 159 | 160 | -- Get all the details from the teachers table. 161 | SELECT * 162 | FROM teacher; 163 | 164 | -- Get the last names and birthdays of all the teachers. 165 | SELECT last_name, dob 166 | FROM teacher; 167 | 168 | 169 | -- Find all courses in English 170 | SELECT * 171 | FROM course 172 | WHERE language = 'ENG'; 173 | 174 | SELECT * 175 | FROM course 176 | WHERE language = 'ENG' 177 | ORDER BY start_date DESC; 178 | 179 | 180 | -- Find all courses in English at B2 level 181 | SELECT * 182 | FROM course 183 | WHERE language = 'ENG' AND level = 'B2'; 184 | 185 | 186 | -- Find all courses in English and all courses at B2 level 187 | SELECT * 188 | FROM course 189 | WHERE language = 'ENG' OR level = 'C1'; 190 | 191 | 192 | -- Find all courses where the language is not English and the level is not C1 193 | SELECT * 194 | FROM course 195 | WHERE NOT language = 'ENG' OR level = 'C1'; 196 | 197 | 198 | -- Get the names and phone numbers of all teachers born before 1990. 199 | SELECT first_name, last_name, phone_no 200 | FROM teacher 201 | WHERE dob < '1990-01-01'; 202 | 203 | -- Do the same as before but use aliasing. 204 | SELECT first_name AS First Name, last_name AS 'Last Name', phone_no AS Telephone 205 | FROM teacher 206 | WHERE dob < '1990-01-01'; 207 | 208 | 209 | -- Find all courses which start in January 210 | SELECT * 211 | FROM course 212 | WHERE start_date BETWEEN '2020-01-01' AND '2020-01-31'; 213 | 214 | 215 | -- Find some intermediate courses 216 | SELECT course_name 217 | FROM course 218 | WHERE course_name LIKE '%interm%'; 219 | 220 | 221 | -- Find participants whose last names are Garcia, Nowak or Mustermann 222 | SELECT first_name, last_name 223 | FROM participant 224 | WHERE last_name IN ('Garcia', 'Nowak', 'Mustermann'); 225 | 226 | 227 | -- Identify teachers who only teach one or two languages 228 | SELECT * 229 | FROM teacher 230 | WHERE language_2 IS NULL; 231 | 232 | 233 | SELECT * 234 | FROM teacher 235 | WHERE language_2 IS NOT NULL; 236 | 237 | 238 | -- Find the average length of a course 239 | SELECT AVG(course_length_weeks) 240 | FROM course; 241 | 242 | 243 | -- Find the average length of a course, grouped by client 244 | SELECT client, AVG(course_length_weeks) 245 | FROM course 246 | GROUP BY client; 247 | 248 | 249 | -- Count the number of courses 250 | SELECT COUNT(*) 251 | FROM course; 252 | 253 | 254 | -- Count the number of courses in English 255 | SELECT COUNT(*) 256 | FROM course 257 | WHERE language = 'Eng'; 258 | 259 | 260 | -- How many courses does the school offer in each language? 261 | SELECT language, COUNT(language) 262 | FROM course 263 | GROUP BY language; 264 | 265 | 266 | -- Find all the teachers whose birthdate is above the average teacher's birthdate 267 | SELECT * 268 | FROM teacher 269 | WHERE dob > 270 | (SELECT AVG(dob) 271 | FROM teacher); 272 | 273 | -- Get the course details for all courses which take place at the client's offices. 274 | SELECT course.course_id, course.course_name, course.language, client.client_name, client.address 275 | FROM course 276 | JOIN client 277 | ON course.client = client.client_id 278 | WHERE course.in_school = FALSE; 279 | 280 | 281 | -- Get the course details for all courses which take place at the client's offices, which are taught 282 | -- by Stefanie Martin (as above, but with added details). 283 | SELECT course.course_id, course.course_name, course.language, client.client_name, client.address 284 | FROM course 285 | JOIN client 286 | ON course.client = client.client_id 287 | WHERE course.in_school = FALSE AND course.teacher = 2; 288 | 289 | 290 | -- Get all particpants in classes taught by Niamh Murphy 291 | SELECT participant.first_name, participant.last_name 292 | FROM participant 293 | JOIN takes_course ON takes_course.participant_id = participant.participant_id 294 | JOIN course ON takes_course.course_id = course.course_id 295 | WHERE takes_course.course_id = 296 | (SELECT takes_course.course_id 297 | WHERE course.teacher = 6); 298 | 299 | 300 | -- NEW TABLE ALERT! 301 | 302 | CREATE TABLE industry_prospects ( 303 | industry VARCHAR(20) PRIMARY KEY, 304 | outlook VARCHAR(20) 305 | ); 306 | 307 | INSERT INTO industry_prospects VALUES 308 | ('Retail', 'Good'), 309 | ('Hospitality', 'Poor'), 310 | ('Logistics', 'Terrible'), 311 | ('Tourism', 'Great'), 312 | ('Events', 'Good'); 313 | 314 | 315 | SELECT client.client_name, client.industry, industry_prospects.outlook 316 | FROM client 317 | JOIN industry_prospects 318 | ON client.industry = industry_prospects.industry; 319 | 320 | SELECT client.client_name, client.industry, industry_prospects.outlook 321 | FROM client 322 | LEFT JOIN industry_prospects 323 | ON client.industry = industry_prospects.industry; 324 | 325 | SELECT client.client_name, client.industry, industry_prospects.outlook 326 | FROM client 327 | RIGHT JOIN industry_prospects 328 | ON client.industry = industry_prospects.industry; 329 | 330 | SELECT client.client_name, client.industry, industry_prospects.outlook 331 | FROM client 332 | FULL JOIN industry_prospects 333 | ON client.industry = industry_prospects.industry; --------------------------------------------------------------------------------