Compare commits
10 Commits
aeb96d9ad5
...
8683007ea6
| Author | SHA1 | Date | |
|---|---|---|---|
| 8683007ea6 | |||
| 33e6f1849a | |||
| 096dd3e83a | |||
| 936c1d3ed4 | |||
| 0d75c1c035 | |||
| 9308f5471a | |||
| 05e2863bfd | |||
| aac9358de5 | |||
| 70f6458e03 | |||
| 453a68b01d |
4
.gitignore
vendored
@@ -1,2 +1,6 @@
|
|||||||
# MySQL Workbench project backup files
|
# MySQL Workbench project backup files
|
||||||
*.mwb.bak
|
*.mwb.bak
|
||||||
|
|
||||||
|
# Python
|
||||||
|
.ipynb_checkpoints
|
||||||
|
__pycache__
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ USE `LittleLemonDB` ;
|
|||||||
-- Table `LittleLemonDB`.`Addresses`
|
-- Table `LittleLemonDB`.`Addresses`
|
||||||
-- -----------------------------------------------------
|
-- -----------------------------------------------------
|
||||||
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Addresses` (
|
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Addresses` (
|
||||||
`AddressID` INT NOT NULL,
|
`AddressID` INT NOT NULL AUTO_INCREMENT,
|
||||||
`Street` VARCHAR(255) NOT NULL,
|
`Street` VARCHAR(255) NOT NULL,
|
||||||
`PostalCode` VARCHAR(12) NOT NULL,
|
`PostalCode` VARCHAR(12) NOT NULL,
|
||||||
`City` VARCHAR(255) NOT NULL,
|
`City` VARCHAR(255) NOT NULL,
|
||||||
@@ -32,7 +32,7 @@ ENGINE = InnoDB;
|
|||||||
-- Table `LittleLemonDB`.`Customers`
|
-- Table `LittleLemonDB`.`Customers`
|
||||||
-- -----------------------------------------------------
|
-- -----------------------------------------------------
|
||||||
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Customers` (
|
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Customers` (
|
||||||
`CustomerID` INT NOT NULL,
|
`CustomerID` INT NOT NULL AUTO_INCREMENT,
|
||||||
`FirstName` VARCHAR(255) NOT NULL,
|
`FirstName` VARCHAR(255) NOT NULL,
|
||||||
`LastName` VARCHAR(255) NOT NULL,
|
`LastName` VARCHAR(255) NOT NULL,
|
||||||
`PhoneNumber` VARCHAR(45) NOT NULL,
|
`PhoneNumber` VARCHAR(45) NOT NULL,
|
||||||
@@ -52,7 +52,7 @@ ENGINE = InnoDB;
|
|||||||
-- Table `LittleLemonDB`.`Employees`
|
-- Table `LittleLemonDB`.`Employees`
|
||||||
-- -----------------------------------------------------
|
-- -----------------------------------------------------
|
||||||
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Employees` (
|
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Employees` (
|
||||||
`EmployeeID` INT NOT NULL,
|
`EmployeeID` INT NOT NULL AUTO_INCREMENT,
|
||||||
`FirstName` VARCHAR(255) NOT NULL,
|
`FirstName` VARCHAR(255) NOT NULL,
|
||||||
`LastName` VARCHAR(255) NOT NULL,
|
`LastName` VARCHAR(255) NOT NULL,
|
||||||
`PhoneNumber` VARCHAR(45) NOT NULL,
|
`PhoneNumber` VARCHAR(45) NOT NULL,
|
||||||
@@ -74,7 +74,7 @@ ENGINE = InnoDB;
|
|||||||
-- Table `LittleLemonDB`.`Bookings`
|
-- Table `LittleLemonDB`.`Bookings`
|
||||||
-- -----------------------------------------------------
|
-- -----------------------------------------------------
|
||||||
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Bookings` (
|
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Bookings` (
|
||||||
`BookingID` INT NOT NULL,
|
`BookingID` INT NOT NULL AUTO_INCREMENT,
|
||||||
`Reserved` DATETIME NOT NULL,
|
`Reserved` DATETIME NOT NULL,
|
||||||
`TableNumber` INT NOT NULL,
|
`TableNumber` INT NOT NULL,
|
||||||
`CustomerID` INT NOT NULL,
|
`CustomerID` INT NOT NULL,
|
||||||
@@ -99,7 +99,7 @@ ENGINE = InnoDB;
|
|||||||
-- Table `LittleLemonDB`.`MenuItems`
|
-- Table `LittleLemonDB`.`MenuItems`
|
||||||
-- -----------------------------------------------------
|
-- -----------------------------------------------------
|
||||||
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`MenuItems` (
|
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`MenuItems` (
|
||||||
`MenuItemID` INT NOT NULL,
|
`MenuItemID` INT NOT NULL AUTO_INCREMENT,
|
||||||
`Name` VARCHAR(255) NOT NULL,
|
`Name` VARCHAR(255) NOT NULL,
|
||||||
`Category` VARCHAR(255) NOT NULL,
|
`Category` VARCHAR(255) NOT NULL,
|
||||||
`Price` DECIMAL(6,2) NOT NULL,
|
`Price` DECIMAL(6,2) NOT NULL,
|
||||||
@@ -112,7 +112,7 @@ ENGINE = InnoDB;
|
|||||||
-- Table `LittleLemonDB`.`Orders`
|
-- Table `LittleLemonDB`.`Orders`
|
||||||
-- -----------------------------------------------------
|
-- -----------------------------------------------------
|
||||||
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Orders` (
|
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`Orders` (
|
||||||
`OrderID` INT NOT NULL,
|
`OrderID` INT NOT NULL AUTO_INCREMENT,
|
||||||
`Started` DATETIME NOT NULL,
|
`Started` DATETIME NOT NULL,
|
||||||
`Finished` DATETIME NULL,
|
`Finished` DATETIME NULL,
|
||||||
`BillAmount` DECIMAL(10,2) NULL,
|
`BillAmount` DECIMAL(10,2) NULL,
|
||||||
@@ -131,7 +131,7 @@ ENGINE = InnoDB;
|
|||||||
-- Table `LittleLemonDB`.`OrderItems`
|
-- Table `LittleLemonDB`.`OrderItems`
|
||||||
-- -----------------------------------------------------
|
-- -----------------------------------------------------
|
||||||
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`OrderItems` (
|
CREATE TABLE IF NOT EXISTS `LittleLemonDB`.`OrderItems` (
|
||||||
`OrderItemID` INT NOT NULL,
|
`OrderItemID` INT NOT NULL AUTO_INCREMENT,
|
||||||
`Ordered` DATETIME NOT NULL,
|
`Ordered` DATETIME NOT NULL,
|
||||||
`Delivered` DATETIME NULL,
|
`Delivered` DATETIME NULL,
|
||||||
`DeliveryStatus` VARCHAR(45) NOT NULL,
|
`DeliveryStatus` VARCHAR(45) NOT NULL,
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
BIN
analysis/LittleLemonAnalysis.twbx
Normal file
BIN
analysis/cuisine_sales_profit_bar_chart.png
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
analysis/customer_dashboard_filtered.png
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
analysis/customer_dashboard_unfiltered.png
Normal file
|
After Width: | Height: | Size: 285 KiB |
BIN
analysis/customer_sales_bar_chart.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
analysis/data_source.png
Normal file
|
After Width: | Height: | Size: 399 KiB |
BIN
analysis/profit_line_chart.png
Normal file
|
After Width: | Height: | Size: 247 KiB |
BIN
analysis/sales_bubble_chart.png
Normal file
|
After Width: | Height: | Size: 329 KiB |
6
env.yml
@@ -2,11 +2,11 @@ name: capstone-project
|
|||||||
channels:
|
channels:
|
||||||
- conda-forge
|
- conda-forge
|
||||||
dependencies:
|
dependencies:
|
||||||
- pip
|
|
||||||
- python=3.13
|
- python=3.13
|
||||||
- pynvim
|
- pip
|
||||||
- pytest
|
- jupyter
|
||||||
- mysql-connector-python
|
- mysql-connector-python
|
||||||
|
- pynvim
|
||||||
- pip:
|
- pip:
|
||||||
- ruff
|
- ruff
|
||||||
- basedpyright
|
- basedpyright
|
||||||
|
|||||||
216
promotional_campaign.ipynb
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "3228e84e-083c-48f6-9913-9d96e2fd0a2a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Promotional campaign"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "71a559ef-75a7-4aca-86aa-10629e047222",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Imports"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "8fe32f7f-09b3-4d9a-af26-4146c500bf44",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from decimal import Decimal\n",
|
||||||
|
"from mysql.connector import CMySQLConnection, Error, connect\n",
|
||||||
|
"from mysql.connector.cursor_cext import CMySQLCursor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "70da0c3b-ae18-4b60-a7eb-1c0c75c3677a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Task 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "ac95c33d-3ead-4dab-b007-4f20d37f7386",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"connection = connect(\n",
|
||||||
|
" user=\"tobias\",\n",
|
||||||
|
" unix_socket=\"/run/mysqld/mysqld.sock\",\n",
|
||||||
|
" database=\"LittleLemonDB\",\n",
|
||||||
|
" use_pure=False,\n",
|
||||||
|
" autocommit=True,\n",
|
||||||
|
")\n",
|
||||||
|
"assert isinstance(connection, CMySQLConnection)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "19e74d2d-2b40-4a1b-a57e-38f27106220b",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Task 2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "1b386dae-78e4-44db-90e5-6da378de16fe",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Tables:\n",
|
||||||
|
" Addresses\n",
|
||||||
|
" Bookings\n",
|
||||||
|
" Customers\n",
|
||||||
|
" Employees\n",
|
||||||
|
" MenuItems\n",
|
||||||
|
" OrderItems\n",
|
||||||
|
" Orders\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"try:\n",
|
||||||
|
" with connection.cursor() as cursor:\n",
|
||||||
|
" assert isinstance(cursor, CMySQLCursor)\n",
|
||||||
|
"\n",
|
||||||
|
" _ = cursor.execute(\"show tables\")\n",
|
||||||
|
" print(\"Tables:\")\n",
|
||||||
|
" for (table_name,) in cursor:\n",
|
||||||
|
" print(f\" {table_name}\")\n",
|
||||||
|
"except Error as err:\n",
|
||||||
|
" print(err)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "62e2485b-1391-4fc6-aa73-35d0ebd8e95d",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Task 3\n",
|
||||||
|
"**SQL query in `sql/promotional_campaign.sql`:**\n",
|
||||||
|
"```sql\n",
|
||||||
|
"select\n",
|
||||||
|
" C.FirstName,\n",
|
||||||
|
" C.LastName,\n",
|
||||||
|
" C.PhoneNumber,\n",
|
||||||
|
" C.EmailAddress,\n",
|
||||||
|
" max(O.BillAmount) as MaxBillAmount\n",
|
||||||
|
"from Orders as O\n",
|
||||||
|
"inner join Bookings as B on O.BookingID = B.BookingID\n",
|
||||||
|
"inner join Customers as C on B.CustomerID = C.CustomerID\n",
|
||||||
|
"group by C.CustomerID\n",
|
||||||
|
"having MaxBillAmount > 60.00;\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "214d0b0e-dd5b-4113-b6d7-aca020655ef3",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"\n",
|
||||||
|
"Customers that placed an order greater then 60.00€:\n",
|
||||||
|
" Li Wei Zhang\n",
|
||||||
|
" Minimum bill amount: 82.50€\n",
|
||||||
|
" Phone number: +86123456789\n",
|
||||||
|
" Email address: li.wei.zhang@example.com\n",
|
||||||
|
" Ivanov Petrov\n",
|
||||||
|
" Minimum bill amount: 150.50€\n",
|
||||||
|
" Phone number: +70987654321\n",
|
||||||
|
" Email address: ivanov.petrov@example.com\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"with open(\"./sql/promotional_campaign.sql\") as promo_campaign_file:\n",
|
||||||
|
" promo_campain_request = promo_campaign_file.read()\n",
|
||||||
|
" \n",
|
||||||
|
"try:\n",
|
||||||
|
" with connection.cursor() as cursor:\n",
|
||||||
|
" assert isinstance(cursor, CMySQLCursor)\n",
|
||||||
|
" _ = cursor.execute(promo_campain_request)\n",
|
||||||
|
"\n",
|
||||||
|
" print()\n",
|
||||||
|
"\n",
|
||||||
|
" print(\"Customers that placed an order greater then 60.00€:\")\n",
|
||||||
|
" for (\n",
|
||||||
|
" first_name,\n",
|
||||||
|
" last_name,\n",
|
||||||
|
" phone_number,\n",
|
||||||
|
" email_address,\n",
|
||||||
|
" min_bill_amount,\n",
|
||||||
|
" ) in cursor:\n",
|
||||||
|
" assert isinstance(first_name, str)\n",
|
||||||
|
" assert isinstance(last_name, str)\n",
|
||||||
|
" assert isinstance(phone_number, str)\n",
|
||||||
|
" assert isinstance(email_address, str | None)\n",
|
||||||
|
" assert isinstance(min_bill_amount, Decimal)\n",
|
||||||
|
" print(f\" {first_name} {last_name}\")\n",
|
||||||
|
" print(f\" Minimum bill amount: {min_bill_amount}€\")\n",
|
||||||
|
" print(f\" Phone number: {phone_number}\")\n",
|
||||||
|
" if email_address:\n",
|
||||||
|
" print(f\" Email address: {email_address}\")\n",
|
||||||
|
"except Error as err:\n",
|
||||||
|
" print(err)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "be3c702d-5ab6-47a6-a19b-4e26aefdbd6e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Cleanup"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "e7f0a6dc-4940-4f8b-a89c-e714e9d375ba",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"connection.close()"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
19
pyproject.toml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[tool.sqlfluff.core]
|
||||||
|
dialiact = "mysql"
|
||||||
|
max_line_length = 110
|
||||||
|
exclude_rules = "ST06"
|
||||||
|
|
||||||
|
[tool.sqlfluff.rules.capitalisation.keywords]
|
||||||
|
capitalisation_policy = "lower"
|
||||||
|
|
||||||
|
[tool.sqlfluff.rules.capitalisation.identifiers]
|
||||||
|
extended_capitalisation_policy = "pascal"
|
||||||
|
|
||||||
|
[tool.sqlfluff.rules.capitalisation.types]
|
||||||
|
extended_capitalisation_policy = "lower"
|
||||||
|
|
||||||
|
[tool.sqlfluff.rules.references.keywords]
|
||||||
|
ignore_words = "role"
|
||||||
|
|
||||||
|
[tool.sqlfluff.indentation]
|
||||||
|
allow_implicit_indents = true
|
||||||
15
sql/add_booking.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
-- modify bookings - task 1
|
||||||
|
-- changes:
|
||||||
|
-- changed BookingDate (Reserved) data type from date to datetime, because I assumed that Little Lemon
|
||||||
|
-- allows wants bookings per day and table - a table is considered blocked for 2 hours
|
||||||
|
-- added EmployeeID input parameter
|
||||||
|
-- noqa: disable=CP03,LT02,RF03
|
||||||
|
create procedure AddBooking (
|
||||||
|
in BookingID int, in Reserved datetime, in TableNumber int, in CustomerID int, in EmployeeID int
|
||||||
|
)
|
||||||
|
begin
|
||||||
|
insert into Bookings (BookingID, Reserved, TableNumber, CustomerID, EmployeeID) values (
|
||||||
|
BookingID, Reserved, TableNumber, CustomerID, EmployeeID
|
||||||
|
);
|
||||||
|
select concat("New booking added") as Confirmation;
|
||||||
|
end
|
||||||
30
sql/add_valid_booking.sql
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
-- available bookings - task 3
|
||||||
|
-- changes:
|
||||||
|
-- changed BookingDate (Reserved) data type from date to datetime, because I assumed that Little Lemon
|
||||||
|
-- allows wants bookings per day and table - a table is considered blocked for 2 hours
|
||||||
|
-- added CustomerID and EmployeeID input parameters
|
||||||
|
-- noqa: disable=CP03,LT02,RF03
|
||||||
|
--
|
||||||
|
create procedure AddValidBooking (
|
||||||
|
in Reserved datetime, in TableNumber int, in CustomerID int, in EmployeeID int
|
||||||
|
)
|
||||||
|
begin
|
||||||
|
start transaction;
|
||||||
|
|
||||||
|
if TableIsFree(Reserved, TableNumber) then
|
||||||
|
insert into Bookings (Reserved, TableNumber, CustomerID, EmployeeID) values (
|
||||||
|
Reserved, TableNumber, CustomerID, EmployeeID
|
||||||
|
);
|
||||||
|
commit;
|
||||||
|
select concat(
|
||||||
|
"Table ", TableNumber,
|
||||||
|
" was free - booking accepted (BookingID=", (select last_insert_id()), ')'
|
||||||
|
) as BookingStatus;
|
||||||
|
else
|
||||||
|
rollback;
|
||||||
|
select concat(
|
||||||
|
"Table ", TableNumber,
|
||||||
|
" is already booked - booking cancelled"
|
||||||
|
) as BookingStatus;
|
||||||
|
end if;
|
||||||
|
end
|
||||||
97
sql/available_booking_results.txt
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# Task 1
|
||||||
|
> source ./example_bookings.sql
|
||||||
|
> select * from `Bookings` where `BookingID` between 11 and 14
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| BookingID | Reserved | TableNumber | CustomerID | EmployeeID |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| 11 | 2022-10-14 18:00:00 | 5 | 1 | 1 |
|
||||||
|
| 12 | 2022-11-12 19:30:00 | 3 | 3 | 1 |
|
||||||
|
| 13 | 2022-10-11 18:45:00 | 2 | 2 | 1 |
|
||||||
|
| 14 | 2022-10-13 19:15:00 | 2 | 1 | 1 |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
|
||||||
|
# Task 2
|
||||||
|
> delimiter $
|
||||||
|
> source ./table_is_free.sql
|
||||||
|
> source ./check_booking.sql
|
||||||
|
> delimiter ;
|
||||||
|
> call CheckBooking("2022-11-12 18:15:00", 3, @IsFree);
|
||||||
|
+---------------------------+
|
||||||
|
| BookingStatus |
|
||||||
|
+---------------------------+
|
||||||
|
| Table 3 is already booked |
|
||||||
|
+---------------------------+
|
||||||
|
> select @IsFree;
|
||||||
|
+---------+
|
||||||
|
| @IsFree |
|
||||||
|
+---------+
|
||||||
|
| 0 |
|
||||||
|
+---------+
|
||||||
|
> call CheckBooking("2022-11-12 17:15:00", 3, @IsFree);
|
||||||
|
+-----------------+
|
||||||
|
| BookingStatus |
|
||||||
|
+-----------------+
|
||||||
|
| Table 3 is free |
|
||||||
|
+-----------------+
|
||||||
|
> select @IsFree;
|
||||||
|
+---------+
|
||||||
|
| @IsFree |
|
||||||
|
+---------+
|
||||||
|
| 1 |
|
||||||
|
+---------+
|
||||||
|
|
||||||
|
# Task 3
|
||||||
|
> delimiter $
|
||||||
|
> source ./add_valid_booking.sql
|
||||||
|
> delimiter ;
|
||||||
|
> call AddValidBooking("2022-11-12 18:15:00", 3, 4, 1);
|
||||||
|
+-----------------------------------------------+
|
||||||
|
| BookingStatus |
|
||||||
|
+-----------------------------------------------+
|
||||||
|
| Table 3 is already booked - booking cancelled |
|
||||||
|
+-----------------------------------------------+
|
||||||
|
> select * from `Bookings`
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| BookingID | Reserved | TableNumber | CustomerID | EmployeeID |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| 1 | 2024-11-14 18:00:00 | 1 | 3 | 1 |
|
||||||
|
| 2 | 2024-11-14 19:30:00 | 2 | 2 | 1 |
|
||||||
|
| 3 | 2024-11-14 18:45:00 | 3 | 4 | 1 |
|
||||||
|
| 4 | 2024-11-14 19:15:00 | 4 | 1 | 2 |
|
||||||
|
| 5 | 2024-11-14 18:30:00 | 5 | 6 | 2 |
|
||||||
|
| 6 | 2024-11-14 19:00:00 | 6 | 5 | 2 |
|
||||||
|
| 7 | 2024-11-15 18:15:00 | 1 | 7 | 5 |
|
||||||
|
| 8 | 2024-11-15 19:45:00 | 2 | 8 | 5 |
|
||||||
|
| 9 | 2024-11-15 18:30:00 | 3 | 9 | 2 |
|
||||||
|
| 10 | 2024-11-15 19:00:00 | 4 | 10 | 5 |
|
||||||
|
| 11 | 2022-10-14 18:00:00 | 5 | 1 | 1 |
|
||||||
|
| 12 | 2022-11-12 19:30:00 | 3 | 3 | 1 |
|
||||||
|
| 13 | 2022-10-11 18:45:00 | 2 | 2 | 1 |
|
||||||
|
| 14 | 2022-10-13 19:15:00 | 2 | 1 | 1 |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
> call AddValidBooking("2022-11-12 17:15:00", 3, 4, 1);
|
||||||
|
+----------------------------------------------------+
|
||||||
|
| BookingStatus |
|
||||||
|
+----------------------------------------------------+
|
||||||
|
| Table 3 was free - booking accepted (BookingID=15) |
|
||||||
|
+----------------------------------------------------+
|
||||||
|
> select * from `Bookings`
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| BookingID | Reserved | TableNumber | CustomerID | EmployeeID |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| 1 | 2024-11-14 18:00:00 | 1 | 3 | 1 |
|
||||||
|
| 2 | 2024-11-14 19:30:00 | 2 | 2 | 1 |
|
||||||
|
| 3 | 2024-11-14 18:45:00 | 3 | 4 | 1 |
|
||||||
|
| 4 | 2024-11-14 19:15:00 | 4 | 1 | 2 |
|
||||||
|
| 5 | 2024-11-14 18:30:00 | 5 | 6 | 2 |
|
||||||
|
| 6 | 2024-11-14 19:00:00 | 6 | 5 | 2 |
|
||||||
|
| 7 | 2024-11-15 18:15:00 | 1 | 7 | 5 |
|
||||||
|
| 8 | 2024-11-15 19:45:00 | 2 | 8 | 5 |
|
||||||
|
| 9 | 2024-11-15 18:30:00 | 3 | 9 | 2 |
|
||||||
|
| 10 | 2024-11-15 19:00:00 | 4 | 10 | 5 |
|
||||||
|
| 11 | 2022-10-14 18:00:00 | 5 | 1 | 1 |
|
||||||
|
| 12 | 2022-11-12 19:30:00 | 3 | 3 | 1 |
|
||||||
|
| 13 | 2022-10-11 18:45:00 | 2 | 2 | 1 |
|
||||||
|
| 14 | 2022-10-13 19:15:00 | 2 | 1 | 1 |
|
||||||
|
| 15 | 2022-11-12 17:15:00 | 3 | 4 | 1 |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
13
sql/cancel_booking.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
-- modify bookings - task 3
|
||||||
|
-- add and update bookings - task 3
|
||||||
|
-- noqa: disable=CP03,LT02,RF03
|
||||||
|
create procedure CancelBooking (in BookingID int)
|
||||||
|
begin
|
||||||
|
delete from Bookings as B
|
||||||
|
where B.BookingID = BookingID;
|
||||||
|
if row_count() = 1 then
|
||||||
|
select concat("Booking ", BookingID, " cancelled") as Confirmation;
|
||||||
|
else
|
||||||
|
select concat("Booking ", BookingID, " not cancelled - missing booking") as Confirmation;
|
||||||
|
end if;
|
||||||
|
end
|
||||||
9
sql/cancel_order.sql
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-- query optimization - task 3
|
||||||
|
-- noqa: disable=CP03
|
||||||
|
create procedure CancelOrder (in TargetOrderID int)
|
||||||
|
begin
|
||||||
|
delete from Orders
|
||||||
|
where OrderID = TargetOrderID;
|
||||||
|
|
||||||
|
select concat("Order ", TargetOrderID, if(row_count() = 1, " is cancelled", " doesn't exist")) as Confirmation;
|
||||||
|
end
|
||||||
10
sql/check_booking.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
-- available bookings - task 2
|
||||||
|
-- changes:
|
||||||
|
-- changed BookingDate (Reserved) data type from date to datetime, because I assumed that Little Lemon
|
||||||
|
-- allows wants bookings per day and table - a table is considered blocked for 2 hours
|
||||||
|
-- noqa: disable=CP03,LT02,RF03
|
||||||
|
create procedure CheckBooking (in Reserved datetime, in TableNumber int, out IsFree boolean) --
|
||||||
|
begin
|
||||||
|
set IsFree = TableIsFree(Reserved, TableNumber);
|
||||||
|
select concat("Table ", TableNumber, " is ", if(IsFree, "free", "already booked")) as BookingStatus;
|
||||||
|
end
|
||||||
15
sql/create_orders_view.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
-- sales report - task 1
|
||||||
|
-- changes:
|
||||||
|
-- interpreted quantity as the number of ordered items, because I assumed that Little lemon wants
|
||||||
|
-- orders à la carte instead of fixed menus
|
||||||
|
drop view if exists OrdersView;
|
||||||
|
|
||||||
|
create view OrdersView as
|
||||||
|
select
|
||||||
|
O.OrderID,
|
||||||
|
count(OI.MenuItemID) as Quantity,
|
||||||
|
O.BillAmount as Cost
|
||||||
|
from Orders as O
|
||||||
|
inner join OrderItems as OI on O.OrderID = OI.OrderID
|
||||||
|
group by O.OrderID
|
||||||
|
having Quantity > 2;
|
||||||
12
sql/example_bookings.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-- available bookings - task 1
|
||||||
|
-- changes:
|
||||||
|
-- changed BookingDate (Reserved) data type from date to datetime, because I assumed that Little Lemon
|
||||||
|
-- allows wants bookings per day and table - a table is considered blocked for 2 hours
|
||||||
|
-- changed BookingID range from 1-4 to 11-14, because there are already 10 Bookings in my test data set
|
||||||
|
-- added arbitrary EmployeeID that corresponds to the Employee that handled the booking process
|
||||||
|
-- noqa: disable=CP03
|
||||||
|
insert into Bookings (BookingID, Reserved, TableNumber, CustomerID, EmployeeID) values
|
||||||
|
(11, '2022-10-14 18:00:00', 5, 1, 1),
|
||||||
|
(12, '2022-11-12 19:30:00', 3, 3, 1),
|
||||||
|
(13, '2022-10-11 18:45:00', 2, 2, 1),
|
||||||
|
(14, '2022-10-13 19:15:00', 2, 1, 1);
|
||||||
47
sql/get_expensive_orders.sql
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
-- sales report - task 2
|
||||||
|
-- changes:
|
||||||
|
-- removed menu name, because I assumed that Little lemon wants orders à la carte instead of fixed menus
|
||||||
|
-- changed cost cutoff from 150.00 to 75.00, because I wanted more than one test result
|
||||||
|
with
|
||||||
|
GroupedOrderItems as (
|
||||||
|
select
|
||||||
|
OI.OrderID,
|
||||||
|
MI.Category,
|
||||||
|
concat(MI.Name, " (", count(OI.OrderItemID), "x)") as Item
|
||||||
|
from OrderItems as OI
|
||||||
|
inner join MenuItems as MI on OI.MenuItemID = MI.MenuItemID
|
||||||
|
group by OI.OrderID, MI.Category, OI.MenuItemID
|
||||||
|
),
|
||||||
|
|
||||||
|
MainOrderItems as (
|
||||||
|
select
|
||||||
|
OrderID,
|
||||||
|
group_concat(Item separator '\n') as Items
|
||||||
|
from GroupedOrderItems
|
||||||
|
where Category = "Main"
|
||||||
|
group by OrderID
|
||||||
|
),
|
||||||
|
|
||||||
|
StarterOrderItems as (
|
||||||
|
select
|
||||||
|
OrderID,
|
||||||
|
group_concat(Item separator '\n') as Items
|
||||||
|
from GroupedOrderItems
|
||||||
|
where Category = "Starter"
|
||||||
|
group by OrderID
|
||||||
|
)
|
||||||
|
|
||||||
|
select
|
||||||
|
C.CustomerID,
|
||||||
|
concat(C.FirstName, " ", C.LastName) as FullName,
|
||||||
|
O.OrderID,
|
||||||
|
O.BillAmount as Cost,
|
||||||
|
coalesce(MOI.Items, "") as Mains,
|
||||||
|
coalesce(SOI.Items, "") as Starters
|
||||||
|
from Orders as O
|
||||||
|
inner join Bookings as B on O.BookingID = B.BookingID
|
||||||
|
inner join Customers as C on B.CustomerID = C.CustomerID
|
||||||
|
left join MainOrderItems as MOI on O.OrderID = MOI.OrderID
|
||||||
|
left join StarterOrderItems as SOI on O.OrderID = SOI.OrderID
|
||||||
|
where O.BillAmount > 75.00
|
||||||
|
group by O.OrderID;
|
||||||
12
sql/get_max_quantity.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-- query optimization - task 1
|
||||||
|
-- changes:
|
||||||
|
-- interpreted quantity as the number of items in an order, because I assumed that Little lemon wants
|
||||||
|
-- orders à la carte instead of fixed menus
|
||||||
|
|
||||||
|
create procedure GetMaxQuantity () -- noqa: disable=CP03
|
||||||
|
select count(OI.OrderItemID) as MaxQuantityInOrder
|
||||||
|
from MenuItems as MI
|
||||||
|
inner join OrderItems as OI on MI.MenuItemID = OI.MenuItemID
|
||||||
|
group by OI.OrderID
|
||||||
|
order by MaxQuantityInOrder desc
|
||||||
|
limit 1
|
||||||
15
sql/get_order_detail.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
-- query optimization - task 2
|
||||||
|
-- changes:
|
||||||
|
-- interpreted quantity as the number of items in an order, because I assumed that Little lemon wants
|
||||||
|
-- orders à la carte instead of fixed menus
|
||||||
|
|
||||||
|
prepare GetOrderDetail from "
|
||||||
|
select
|
||||||
|
O.OrderID,
|
||||||
|
count(OI.MenuItemID) as Quantity,
|
||||||
|
O.BillAmount as Cost
|
||||||
|
from Orders as O
|
||||||
|
inner join OrderItems as OI on O.OrderID = OI.OrderID
|
||||||
|
inner join Bookings as B on O.BookingID = B.BookingID
|
||||||
|
where B.CustomerID = ?;
|
||||||
|
";
|
||||||
11
sql/get_popular_menu_items.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
-- sales report - task 3
|
||||||
|
-- changes:
|
||||||
|
-- replaced menu name with menu item name, because I assumed that Little lemon wants orders à la carte
|
||||||
|
-- instead of fixed menus
|
||||||
|
select
|
||||||
|
MI.Name,
|
||||||
|
count(OI.OrderItemID) as OrderQuantity
|
||||||
|
from MenuItems as MI
|
||||||
|
inner join OrderItems as OI on MI.MenuItemID = OI.MenuItemID
|
||||||
|
group by OI.MenuItemID
|
||||||
|
having OrderQuantity > 2;
|
||||||
126
sql/init_data.sql
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
delete from MenuItems;
|
||||||
|
insert into MenuItems (MenuItemID, Name, Category, Price) values
|
||||||
|
(1, "Grilled Artichokes", "Starter", 6.00),
|
||||||
|
(2, "Lentil Soup", "Starter", 7.00),
|
||||||
|
(3, "Humus Plate", "Starter", 6.00),
|
||||||
|
(4, "Eggplant Bruschetta", "Starter", 7.00),
|
||||||
|
(5, "Gigantes Plaki", "Main", 14.00),
|
||||||
|
(6, "Minestrone", "Main", 16.00),
|
||||||
|
(7, "Moussaka", "Main", 17.00),
|
||||||
|
(8, "Pasta alla Norma", "Main", 12.00),
|
||||||
|
(9, "Tabbouleh", "Salad", 8.00),
|
||||||
|
(10, "Green Bean Salad", "Salad", 8.00),
|
||||||
|
(11, "Tomato Salad", "Salad", 9.50),
|
||||||
|
(12, "Fennel Salad", "Salad", 8.50),
|
||||||
|
(13, "Fruit Salad", "Desert", 7.00),
|
||||||
|
(14, "Roasted Grapes", "Desert", 6.50),
|
||||||
|
(15, "Grilled Mango", "Desert", 8.50),
|
||||||
|
(16, "Grilled Waterlemon", "Desert", 8.50);
|
||||||
|
|
||||||
|
delete from Addresses;
|
||||||
|
insert into Addresses (AddressID, Street, PostalCode, City, Country) values
|
||||||
|
(1, 'Hauptstraße 1', '10115', 'Berlin', 'Germany'),
|
||||||
|
(2, 'Friedrichstraße 56', '10119', 'Berlin', 'Germany'),
|
||||||
|
(3, 'Kurfürstenstraße 135', '10115', 'Berlin', 'Germany'),
|
||||||
|
(4, 'Altenhofen 168', '10623', 'Berlin', 'Germany'),
|
||||||
|
(5, 'Hauptstraße 180', '10116', 'Berlin', 'Germany');
|
||||||
|
|
||||||
|
delete from Employees;
|
||||||
|
insert into Employees (
|
||||||
|
EmployeeID, FirstName, LastName, PhoneNumber, EmailAddress, Role, AnnualSalary, AddressID
|
||||||
|
) values
|
||||||
|
(1, 'Mario', 'Gollini', '+4915123456789', 'mario.gollini@littlelemon.de', 'Manager', 72383.00, 1),
|
||||||
|
(2, 'Adrian', 'Gollini', '+4916198765432', 'adrian.gollini@littlelemon.de', 'Receptionist', 74083.00, 2),
|
||||||
|
(3, 'Giorgos', 'Dioudis', '+4917654321098', 'giogos.dioudis@littlelemon.de', 'Assistant Chef', 77912.00, 3),
|
||||||
|
(4, 'Fatma', 'Kaya', '+4918765432190', 'fatma.kaya@littlelemon.de', 'Head Chef', 79314.00, 4),
|
||||||
|
(5, 'Elena', 'Salvai', '+4919876543210', 'elena.salvai@littlelemon.de', 'Waiter', 78921.00, 5);
|
||||||
|
|
||||||
|
delete from Customers;
|
||||||
|
insert into Customers (
|
||||||
|
CustomerID, FirstName, LastName, PhoneNumber, EmailAddress, AddressID
|
||||||
|
)
|
||||||
|
values
|
||||||
|
(1, 'Ahmed', 'Mohamed', '+20212345678', 'ahmed.mohamed@example.com', null),
|
||||||
|
(2, 'Sophie', 'Dupont', '+33612345678', 'sophie.dupont@example.com', null),
|
||||||
|
(3, 'Li Wei', 'Zhang', '+86123456789', 'li.wei.zhang@example.com', null),
|
||||||
|
(4, 'Maria', 'Rodriguez', '+34612345678', 'maria.rodriguez@example.com', null),
|
||||||
|
(5, 'Ivanov', 'Petrov', '+70987654321', 'ivanov.petrov@example.com', null),
|
||||||
|
(6, 'José', 'Martinez', '+54987654321', 'jose.martinez@example.com', null),
|
||||||
|
(7, 'Maria', 'Schmidt', '+49987654321', 'maria.schmidt@example.com', null),
|
||||||
|
(8, 'Thomas', 'Müller', '+44987654321', 'thomas.mueller@example.com', null),
|
||||||
|
(9, 'Ramón', 'García', '+58987654321', 'ramon.garcia@example.com', null),
|
||||||
|
(10, 'Lee', 'Kim', '+82109876543', 'lee.kim@example.com', null);
|
||||||
|
|
||||||
|
delete from Bookings;
|
||||||
|
insert into Bookings (BookingID, Reserved, TableNumber, CustomerID, EmployeeID)
|
||||||
|
values
|
||||||
|
(1, '2024-11-14 18:00:00', 1, 3, 1),
|
||||||
|
(2, '2024-11-14 19:30:00', 2, 2, 1),
|
||||||
|
(3, '2024-11-14 18:45:00', 3, 4, 1),
|
||||||
|
(4, '2024-11-14 19:15:00', 4, 1, 2),
|
||||||
|
(5, '2024-11-14 18:30:00', 5, 6, 2),
|
||||||
|
(6, '2024-11-14 19:00:00', 6, 5, 2),
|
||||||
|
(7, '2024-11-15 18:15:00', 1, 7, 5),
|
||||||
|
(8, '2024-11-15 19:45:00', 2, 8, 5),
|
||||||
|
(9, '2024-11-15 18:30:00', 3, 9, 2),
|
||||||
|
(10, '2024-11-15 19:00:00', 4, 10, 5);
|
||||||
|
|
||||||
|
insert into Orders (OrderID, Started, Finished, BillAmount, BookingID)
|
||||||
|
values
|
||||||
|
(1, '2024-11-14 18:05:00', '2023-10-01 19:25:00', null, 1),
|
||||||
|
(2, '2024-11-14 19:35:00', '2023-10-02 20:45:00', null, 2),
|
||||||
|
(3, '2024-11-14 19:10:00', '2023-10-03 20:30:00', null, 3),
|
||||||
|
(4, '2024-11-14 19:35:00', '2023-10-04 20:50:00', null, 4),
|
||||||
|
(5, '2024-11-14 19:40:00', '2023-10-05 20:55:00', null, 5),
|
||||||
|
(6, '2024-11-14 19:40:00', '2023-10-06 20:45:00', null, 6);
|
||||||
|
|
||||||
|
insert into OrderItems (OrderItemID, MenuItemID, OrderID, Ordered, Delivered, DeliveryStatus)
|
||||||
|
values
|
||||||
|
(1, 1, 1, '2024-11-14 18:05:00', '2024-11-14 18:25:00', 'Delivered'),
|
||||||
|
(2, 2, 1, '2024-11-14 18:05:00', '2024-11-14 18:25:00', 'Delivered'),
|
||||||
|
(3, 3, 1, '2024-11-14 18:05:00', '2024-11-14 18:25:00', 'Delivered'),
|
||||||
|
(4, 5, 1, '2024-11-14 18:05:00', '2024-11-14 18:40:00', 'Delivered'),
|
||||||
|
(5, 5, 1, '2024-11-14 18:05:00', '2024-11-14 18:40:00', 'Delivered'),
|
||||||
|
(6, 8, 1, '2024-11-14 18:05:00', '2024-11-14 18:40:00', 'Delivered'),
|
||||||
|
(7, 14, 1, '2024-11-14 18:05:00', '2024-11-14 19:05:00', 'Delivered'),
|
||||||
|
(8, 15, 1, '2024-11-14 18:05:00', '2024-11-14 19:05:00', 'Delivered'),
|
||||||
|
(9, 16, 1, '2024-11-14 18:05:00', '2024-11-14 19:05:00', 'Delivered'),
|
||||||
|
(10, 2, 2, '2024-11-14 19:35:00', '2024-11-14 19:55:00', 'Delivered'),
|
||||||
|
(11, 5, 2, '2024-11-14 19:35:00', '2024-11-14 20:10:00', 'Delivered'),
|
||||||
|
(12, 13, 2, '2024-11-14 19:35:00', '2024-11-14 20:35:00', 'Delivered'),
|
||||||
|
(13, 4, 3, '2024-11-14 19:10:00', '2024-11-14 19:30:00', 'Delivered'),
|
||||||
|
(14, 7, 3, '2024-11-14 19:10:00', '2024-11-14 19:45:00', 'Delivered'),
|
||||||
|
(15, 13, 3, '2024-11-14 19:10:00', '2024-11-14 20:10:00', 'Delivered'),
|
||||||
|
(16, 3, 4, '2024-11-14 19:35:00', '2024-11-14 19:55:00', 'Delivered'),
|
||||||
|
(17, 6, 4, '2024-11-14 19:35:00', '2024-11-14 20:10:00', 'Delivered'),
|
||||||
|
(18, 13, 4, '2024-11-14 19:35:00', '2024-11-14 20:35:00', 'Delivered'),
|
||||||
|
(19, 9, 5, '2024-11-14 19:40:00', '2024-11-14 20:00:00', 'Delivered'),
|
||||||
|
(20, 8, 5, '2024-11-14 19:40:00', '2024-11-14 20:15:00', 'Delivered'),
|
||||||
|
(22, 2, 6, '2024-11-14 19:40:00', '2024-11-14 19:55:00', 'Delivered'),
|
||||||
|
(23, 4, 6, '2024-11-14 19:40:00', '2024-11-14 19:55:00', 'Delivered'),
|
||||||
|
(24, 2, 6, '2024-11-14 19:40:00', '2024-11-14 19:55:00', 'Delivered'),
|
||||||
|
(25, 3, 6, '2024-11-14 19:40:00', '2024-11-14 19:55:00', 'Delivered'),
|
||||||
|
(26, 1, 6, '2024-11-14 19:40:00', '2024-11-14 19:55:00', 'Delivered'),
|
||||||
|
(27, 6, 6, '2024-11-14 19:40:00', '2024-11-14 20:10:00', 'Delivered'),
|
||||||
|
(28, 6, 6, '2024-11-14 19:40:00', '2024-11-14 20:10:00', 'Delivered'),
|
||||||
|
(29, 5, 6, '2024-11-14 19:40:00', '2024-11-14 20:10:00', 'Delivered'),
|
||||||
|
(30, 5, 6, '2024-11-14 19:40:00', '2024-11-14 20:10:00', 'Delivered'),
|
||||||
|
(31, 7, 6, '2024-11-14 19:40:00', '2024-11-14 20:10:00', 'Delivered'),
|
||||||
|
(32, 15, 6, '2024-11-14 19:40:00', '2024-11-14 20:35:00', 'Delivered'),
|
||||||
|
(33, 14, 6, '2024-11-14 19:40:00', '2024-11-14 20:35:00', 'Delivered'),
|
||||||
|
(34, 15, 6, '2024-11-14 19:40:00', '2024-11-14 20:35:00', 'Delivered'),
|
||||||
|
(35, 16, 6, '2024-11-14 19:40:00', '2024-11-14 20:35:00', 'Delivered'),
|
||||||
|
(36, 16, 6, '2024-11-14 19:40:00', '2024-11-14 20:35:00', 'Delivered');
|
||||||
|
|
||||||
|
update Orders as O
|
||||||
|
inner join
|
||||||
|
(
|
||||||
|
select
|
||||||
|
OI.OrderID,
|
||||||
|
sum(MI.Price) as TotalItemPrice
|
||||||
|
from OrderItems as OI
|
||||||
|
inner join MenuItems as MI on OI.MenuItemID = MI.MenuItemID
|
||||||
|
group by OI.OrderID
|
||||||
|
) as A
|
||||||
|
on O.OrderID = A.OrderID
|
||||||
|
set O.BillAmount = A.TotalItemPrice;
|
||||||
101
sql/modify_bookings_results.txt
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# Task 1
|
||||||
|
> delimiter $
|
||||||
|
> source ./add_booking.sql
|
||||||
|
> delimiter ;
|
||||||
|
> call AddBooking(20, "2024-11-19 19:00:00", 3, 1, 2)
|
||||||
|
+-------------------+
|
||||||
|
| Confirmation |
|
||||||
|
+-------------------+
|
||||||
|
| New booking added |
|
||||||
|
+-------------------+
|
||||||
|
> select * from `Bookings` where `BookingID` = 20
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| BookingID | Reserved | TableNumber | CustomerID | EmployeeID |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| 20 | 2024-11-19 19:00:00 | 3 | 1 | 2 |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
|
||||||
|
# Task 2
|
||||||
|
> delimiter $
|
||||||
|
> source ./update_booking.sql
|
||||||
|
> delimiter ;
|
||||||
|
> call UpdateBooking(20, date_sub((select Reserved from `Bookings` where `BookingID` = 20), interval 1 day))
|
||||||
|
+--------------------+
|
||||||
|
| Confirmation |
|
||||||
|
+--------------------+
|
||||||
|
| Booking 20 updated |
|
||||||
|
+--------------------+
|
||||||
|
> select * from `Bookings` where `BookingID` = 20;
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| BookingID | Reserved | TableNumber | CustomerID | EmployeeID |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| 20 | 2024-11-18 19:00:00 | 3 | 1 | 2 |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
> call UpdateBooking(21, "2024-11-18 15:00:00")
|
||||||
|
+---------------------------------------------+
|
||||||
|
| Confirmation |
|
||||||
|
+---------------------------------------------+
|
||||||
|
| Booking 21 wasn't updated - missing booking |
|
||||||
|
+---------------------------------------------+
|
||||||
|
> select * from `Bookings` where `BookingID` = 21
|
||||||
|
+-----------+----------+-------------+------------+------------+
|
||||||
|
| BookingID | Reserved | TableNumber | CustomerID | EmployeeID |
|
||||||
|
+-----------+----------+-------------+------------+------------+
|
||||||
|
+-----------+----------+-------------+------------+------------+
|
||||||
|
|
||||||
|
# Task 3
|
||||||
|
> delimiter $
|
||||||
|
> source ./cancel_booking.sql
|
||||||
|
> delimiter ;
|
||||||
|
> call CancelBooking(20)
|
||||||
|
+----------------------+
|
||||||
|
| Confirmation |
|
||||||
|
+----------------------+
|
||||||
|
| Booking 20 cancelled |
|
||||||
|
+----------------------+
|
||||||
|
> select * from `Bookings`
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| BookingID | Reserved | TableNumber | CustomerID | EmployeeID |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| 1 | 2024-11-14 18:00:00 | 1 | 3 | 1 |
|
||||||
|
| 2 | 2024-11-14 19:30:00 | 2 | 2 | 1 |
|
||||||
|
| 3 | 2024-11-14 18:45:00 | 3 | 4 | 1 |
|
||||||
|
| 4 | 2024-11-14 19:15:00 | 4 | 1 | 2 |
|
||||||
|
| 5 | 2024-11-14 18:30:00 | 5 | 6 | 2 |
|
||||||
|
| 6 | 2024-11-14 19:00:00 | 6 | 5 | 2 |
|
||||||
|
| 7 | 2024-11-15 18:15:00 | 1 | 7 | 5 |
|
||||||
|
| 8 | 2024-11-15 19:45:00 | 2 | 8 | 5 |
|
||||||
|
| 9 | 2024-11-15 18:30:00 | 3 | 9 | 2 |
|
||||||
|
| 10 | 2024-11-15 19:00:00 | 4 | 10 | 5 |
|
||||||
|
| 11 | 2022-10-14 18:00:00 | 5 | 1 | 1 |
|
||||||
|
| 12 | 2022-11-12 19:30:00 | 3 | 3 | 1 |
|
||||||
|
| 13 | 2022-10-11 18:45:00 | 2 | 2 | 1 |
|
||||||
|
| 14 | 2022-10-13 19:15:00 | 2 | 1 | 1 |
|
||||||
|
| 15 | 2022-11-12 17:15:00 | 3 | 4 | 1 |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
> call CancelBooking(21)
|
||||||
|
+--------------------------------------------+
|
||||||
|
| Confirmation |
|
||||||
|
+--------------------------------------------+
|
||||||
|
| Booking 21 not cancelled - missing booking |
|
||||||
|
+--------------------------------------------+
|
||||||
|
> select * from `Bookings`
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| BookingID | Reserved | TableNumber | CustomerID | EmployeeID |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
|
| 1 | 2024-11-14 18:00:00 | 1 | 3 | 1 |
|
||||||
|
| 2 | 2024-11-14 19:30:00 | 2 | 2 | 1 |
|
||||||
|
| 3 | 2024-11-14 18:45:00 | 3 | 4 | 1 |
|
||||||
|
| 4 | 2024-11-14 19:15:00 | 4 | 1 | 2 |
|
||||||
|
| 5 | 2024-11-14 18:30:00 | 5 | 6 | 2 |
|
||||||
|
| 6 | 2024-11-14 19:00:00 | 6 | 5 | 2 |
|
||||||
|
| 7 | 2024-11-15 18:15:00 | 1 | 7 | 5 |
|
||||||
|
| 8 | 2024-11-15 19:45:00 | 2 | 8 | 5 |
|
||||||
|
| 9 | 2024-11-15 18:30:00 | 3 | 9 | 2 |
|
||||||
|
| 10 | 2024-11-15 19:00:00 | 4 | 10 | 5 |
|
||||||
|
| 11 | 2022-10-14 18:00:00 | 5 | 1 | 1 |
|
||||||
|
| 12 | 2022-11-12 19:30:00 | 3 | 3 | 1 |
|
||||||
|
| 13 | 2022-10-11 18:45:00 | 2 | 2 | 1 |
|
||||||
|
| 14 | 2022-10-13 19:15:00 | 2 | 1 | 1 |
|
||||||
|
| 15 | 2022-11-12 17:15:00 | 3 | 4 | 1 |
|
||||||
|
+-----------+---------------------+-------------+------------+------------+
|
||||||
11
sql/promotional_campaign.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
select
|
||||||
|
C.FirstName,
|
||||||
|
C.LastName,
|
||||||
|
C.PhoneNumber,
|
||||||
|
C.EmailAddress,
|
||||||
|
max(O.BillAmount) as MaxBillAmount
|
||||||
|
from Orders as O
|
||||||
|
inner join Bookings as B on O.BookingID = B.BookingID
|
||||||
|
inner join Customers as C on B.CustomerID = C.CustomerID
|
||||||
|
group by C.CustomerID
|
||||||
|
having MaxBillAmount > 60.00;
|
||||||
47
sql/query_optimization_results.txt
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Task 1
|
||||||
|
> delimiter $
|
||||||
|
> source ./get_max_quantity.sql
|
||||||
|
> delimiter ;
|
||||||
|
> call GetMaxQuantity();
|
||||||
|
+--------------------+
|
||||||
|
| MaxQuantityInOrder |
|
||||||
|
+--------------------+
|
||||||
|
| 15 |
|
||||||
|
+--------------------+
|
||||||
|
|
||||||
|
# Task 2
|
||||||
|
> source ./get_order_detail.sql
|
||||||
|
> set @customerID = 1
|
||||||
|
> execute GetOrderDetail using @customerID
|
||||||
|
+---------+----------+-------+
|
||||||
|
| OrderID | Quantity | Cost |
|
||||||
|
+---------+----------+-------+
|
||||||
|
| 4 | 3 | 29.00 |
|
||||||
|
+---------+----------+-------+
|
||||||
|
|
||||||
|
# Task 3
|
||||||
|
> delimiter $
|
||||||
|
> source ./cancel_order.sql
|
||||||
|
> delimiter ;
|
||||||
|
> call CancelOrder(2)
|
||||||
|
+----------------------+
|
||||||
|
| Confirmation |
|
||||||
|
+----------------------+
|
||||||
|
| Order 2 is cancelled |
|
||||||
|
+----------------------+
|
||||||
|
> select * from `Orders`
|
||||||
|
+---------+---------------------+---------------------+------------+-----------+
|
||||||
|
| OrderID | Started | Finished | BillAmount | BookingID |
|
||||||
|
+---------+---------------------+---------------------+------------+-----------+
|
||||||
|
| 1 | 2024-11-14 18:05:00 | 2023-10-01 19:25:00 | 82.50 | 1 |
|
||||||
|
| 3 | 2024-11-14 19:10:00 | 2023-10-03 20:30:00 | 31.00 | 3 |
|
||||||
|
| 4 | 2024-11-14 19:35:00 | 2023-10-04 20:50:00 | 29.00 | 4 |
|
||||||
|
| 5 | 2024-11-14 19:40:00 | 2023-10-05 20:55:00 | 20.00 | 5 |
|
||||||
|
| 6 | 2024-11-14 19:40:00 | 2023-10-06 20:45:00 | 150.50 | 6 |
|
||||||
|
+---------+---------------------+---------------------+------------+-----------+
|
||||||
|
> call CancelOrder(2)
|
||||||
|
+-----------------------+
|
||||||
|
| Confirmation |
|
||||||
|
+-----------------------+
|
||||||
|
| Order 2 doesn't exist |
|
||||||
|
+-----------------------+
|
||||||
40
sql/sales_report_results.txt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Task 1
|
||||||
|
> source ./create_orders_view.sql
|
||||||
|
> select * from OrdersView;
|
||||||
|
+---------+----------+--------+
|
||||||
|
| OrderID | Quantity | Cost |
|
||||||
|
+---------+----------+--------+
|
||||||
|
| 1 | 9 | 82.50 |
|
||||||
|
| 2 | 3 | 28.00 |
|
||||||
|
| 3 | 3 | 31.00 |
|
||||||
|
| 4 | 3 | 29.00 |
|
||||||
|
| 6 | 15 | 150.50 |
|
||||||
|
+---------+----------+--------+
|
||||||
|
|
||||||
|
# Task 2
|
||||||
|
> source ./get_expensive_orders.sql
|
||||||
|
+------------+---------------+---------+--------+-----------------------+--------------------------+
|
||||||
|
| CustomerID | FullName | OrderID | Cost | Mains | Starters |
|
||||||
|
+------------+---------------+---------+--------+-----------------------+--------------------------+
|
||||||
|
| 3 | Li Wei Zhang | 1 | 82.50 | Gigantes Plaki (2x) | Grilled Artichokes (1x) |
|
||||||
|
| | | | | Pasta alla Norma (1x) | Lentil Soup (1x) |
|
||||||
|
| | | | | | Humus Plate (1x) |
|
||||||
|
| 5 | Ivanov Petrov | 6 | 150.50 | Minestrone (2x) | Lentil Soup (2x) |
|
||||||
|
| | | | | Gigantes Plaki (2x) | Eggplant Bruschetta (1x) |
|
||||||
|
| | | | | Moussaka (1x) | Humus Plate (1x) |
|
||||||
|
| | | | | | Grilled Artichokes (1x) |
|
||||||
|
+------------+---------------+---------+--------+-----------------------+--------------------------+
|
||||||
|
|
||||||
|
# Task 3
|
||||||
|
> source ./get_popular_menu_items.sql
|
||||||
|
+--------------------+---------------+
|
||||||
|
| Name | OrderQuantity |
|
||||||
|
+--------------------+---------------+
|
||||||
|
| Lentil Soup | 4 |
|
||||||
|
| Humus Plate | 3 |
|
||||||
|
| Gigantes Plaki | 5 |
|
||||||
|
| Minestrone | 3 |
|
||||||
|
| Fruit Salad | 3 |
|
||||||
|
| Grilled Mango | 3 |
|
||||||
|
| Grilled Waterlemon | 3 |
|
||||||
|
+--------------------+---------------+
|
||||||
17
sql/table_is_free.sql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
-- available bookings - task 2
|
||||||
|
-- changes:
|
||||||
|
-- changed BookingDate (Reserved) data type from date to datetime, because I assumed that Little Lemon
|
||||||
|
-- allows wants bookings per day and table - a table is considered blocked for 2 hours
|
||||||
|
-- noqa: disable=CP03,LT02,RF03
|
||||||
|
create function TableIsFree(Reserved datetime, TableNumber int)
|
||||||
|
returns boolean
|
||||||
|
deterministic
|
||||||
|
begin
|
||||||
|
return (select not exists (
|
||||||
|
select BookingID
|
||||||
|
from Bookings as B
|
||||||
|
where
|
||||||
|
abs(timestampdiff(second, B.Reserved, Reserved)) < 2 * 60 * 60
|
||||||
|
and B.TableNumber = TableNumber
|
||||||
|
));
|
||||||
|
end
|
||||||
16
sql/update_booking.sql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
-- modify bookings - task 2
|
||||||
|
-- changes:
|
||||||
|
-- changed BookingDate (Reserved) data type from date to datetime, because I assumed that Little Lemon
|
||||||
|
-- allows wants bookings per day and table - a table is considered blocked for 2 hours
|
||||||
|
-- noqa: disable=CP03,LT02,RF03
|
||||||
|
create procedure UpdateBooking (in BookingID int, in Reserved datetime)
|
||||||
|
begin
|
||||||
|
update Bookings as B
|
||||||
|
set B.Reserved = Reserved
|
||||||
|
where B.BookingID = BookingID;
|
||||||
|
if row_count() = 1 then
|
||||||
|
select concat("Booking ", BookingID, " updated") as Confirmation;
|
||||||
|
else
|
||||||
|
select concat("Booking ", BookingID, " wasn't updated - missing booking") as Confirmation;
|
||||||
|
end if;
|
||||||
|
end
|
||||||