diff --git a/Spring-2023/CS-1011/Relational-DB-Assignment/.gitignore b/Spring-2023/CS-1011/Relational-DB-Assignment/.gitignore new file mode 100644 index 0000000..6061583 --- /dev/null +++ b/Spring-2023/CS-1011/Relational-DB-Assignment/.gitignore @@ -0,0 +1 @@ +*.sqlite3 diff --git a/Spring-2023/CS-1011/Relational-DB-Assignment/README.org b/Spring-2023/CS-1011/Relational-DB-Assignment/README.org new file mode 100644 index 0000000..278f78d --- /dev/null +++ b/Spring-2023/CS-1011/Relational-DB-Assignment/README.org @@ -0,0 +1,55 @@ +* Databases: Relational - In-Class Assignment + +You can run the queries in [[./solve.sql]] against a ~sqlite3~ database to solve this assignment +or install [[https://nixos.org/][Nix]] and run [[./solve.bash]]. + +** Answer the Following Questions With Info From [[*Tables]] + +1. What was the total profit across all stores? + - =$34.5= +2. What is the name of the most popular product sold? + - =Toy Story= +3. How much profit did the "East" region make? + - =$13.96= +4. Which city had the highest cost? + - The city with the highest aggregate cost would be =San Francisco=. + - However, the city with the highest /single/ cost would be =New York=. +5. What was the least popular product brand? + - =Big Studios=, because they had no sales. +6. Which city (or cities) sold "Sense and Sensibility"? + - =San Francisco= + +** Tables + +*** STORE +| Store_key | City | Region | +|-----------|---------------|---------| +| 1 | New York | East | +| 2 | Chicago | Central | +| 3 | Atlanta | East | +| 4 | Los Angeles | West | +| 5 | San Francisco | West | +| 6 | Philadelphia | East | + +*** PRODUCT +| Product_key | Description | Brand | +|-------------|-----------------------|-----------------| +| 1 | Beautiful Girls | MKF Studios | +| 2 | Toy Story | Wolf | +| 3 | Sense and Sensibility | Parabuster Inc. | +| 4 | Holday of the Year | Wolf | +| 5 | Pulp Fiction | MKF Studios | +| 6 | The Juror | MKF Studios | +| 7 | From Dusk Till Dawn | Parabuster Inc. | +| 8 | Hellraiser: Bloodline | Big Studios | + +*** SALES_FACT + +| Store_key | Product_key | Sales | Cost | Profit | +|-----------|-------------|-------|------|--------| +| 1 | 6 | 2.39 | 1.15 | 1.24 | +| 1 | 2 | 16.7 | 6.91 | 9.79 | +| 2 | 7 | 7.16 | 2.75 | 4.40 | +| 3 | 2 | 4.77 | 1.84 | 2.93 | +| 5 | 3 | 11.93 | 4.59 | 7.34 | +| 5 | 1 | 14.31 | 5.51 | 8.80 | diff --git a/Spring-2023/CS-1011/Relational-DB-Assignment/cmds.sql b/Spring-2023/CS-1011/Relational-DB-Assignment/cmds.sql new file mode 100644 index 0000000..d03a956 --- /dev/null +++ b/Spring-2023/CS-1011/Relational-DB-Assignment/cmds.sql @@ -0,0 +1,183 @@ +-- ┌────────────────────┐ +-- │STORE TABLE AND DATA│ +-- └────────────────────┘ +DROP TABLE IF EXISTS STORE; + +CREATE TABLE IF NOT EXISTS STORE ( + Store_key INTEGER PRIMARY KEY, + City TEXT NOT NULL, + Region TEXT CHECK (Region IN ('East', 'Central', 'West')) NOT NULL +); + +INSERT INTO + STORE (Store_key, City, Region) +VALUES + (1, 'New York', 'East'), + (2, 'Chicago', 'Central'), + (3, 'Atlanta', 'East'), + (4, 'Los Angeles', 'West'), + (5, 'San Francisco', 'West'), + (6, 'Philadelphia', 'East'); + +-- ┌──────────────────────┐ +-- │PRODUCT TABLE AND DATA│ +-- └──────────────────────┘ +DROP TABLE IF EXISTS PRODUCT; + +CREATE TABLE IF NOT EXISTS PRODUCT ( + Product_key INTEGER PRIMARY KEY, + Description TEXT NOT NULL, + Brand TEXT CHECK ( + Brand IN ( + 'MKF Studios', + 'Wolf', + 'Parabuster Inc.', + 'Big Studios' + ) + ) NOT NULL +); + +INSERT INTO + PRODUCT (Product_key, Description, Brand) +VALUES + (1, 'Beautiful Girls', 'MKF Studios'), + (2, 'Toy Story', 'Wolf'), + (3, 'Sense and Sensibility', 'Parabuster Inc.'), + (4, 'Holday of the Year', 'Wolf'), + (5, 'Pulp Fiction', 'MKF Studios'), + (6, 'The Juror', 'MKF Studios'), + (7, 'From Dusk Till Dawn', 'Parabuster Inc.'), + (8, 'Hellraiser: Bloodline', 'Big Studios'); + +-- ┌─────────────────────────┐ +-- │SALES_FACT TABLE AND DATA│ +-- └─────────────────────────┘ +DROP TABLE IF EXISTS SALES_FACT; + +-- WARN: Storing money AS floats/`REAL` is a big no-no in a real application due to floating point +-- rounding errors. For this purpose it's ok, but for the love of god and all that is holy do NOT +-- store money AS a float. +CREATE TABLE IF NOT EXISTS SALES_FACT ( + Store_key INTEGER NOT NULL, + Product_key INTEGER NOT NULL, + Sales REAL NOT NULL, + Cost REAL NOT NULL, + Profit REAL NOT NULL, + FOREIGN KEY (Store_key) REFERENCES STORE (Store_key), + FOREIGN KEY (Product_key) REFERENCES PRODUCT (Product_key) +); + +INSERT INTO + SALES_FACT (Store_key, Product_key, Sales, Cost, Profit) +VALUES + (1, 6, 2.39, 1.15, 1.24), + (1, 2, 16.7, 6.91, 9.79), + (2, 7, 7.16, 2.75, 4.40), + (3, 2, 4.77, 1.84, 2.93), + (5, 3, 11.93, 4.59, 7.34), + (5, 1, 14.31, 5.51, 8.80); + +--- Answers to Questions --- +-- 1. What was the total profit across all stores? +SELECT + Sum(Profit) AS "Total Profit Across All Stores" +FROM + SALES_FACT; + +-- 2. What is the name of the most popular product sold? +SELECT + Description AS "Name of Most Popular Product" +FROM + ( + SELECT + Max(sf.Sales), + p.Description + FROM + SALES_FACT AS sf + INNER JOIN PRODUCT p ON p.Product_key = sf.Product_key + ); + +-- 3. How much profit did the "East" region make? +SELECT + Sum(Profit) AS "East Region Profits" +FROM + SALES_FACT AS sf + INNER JOIN STORE AS s ON s.Store_key = sf.Store_key + AND s.REGION = 'East'; + +-- 4. Which city had the highest cost? +SELECT + City AS "City With Highest Aggregate Cost" +FROM + ( + SELECT + s.Store_key, + Max(cost_sums) AS "Total Cost", + City + FROM + ( + SELECT + Store_key, + Sum(Cost) AS cost_sums + FROM + SALES_FACT + GROUP BY + Store_key + ) AS sf + INNER JOIN STORE AS s ON s.Store_key = sf.Store_key + ); + +SELECT + City as "City With Highest Single Cost" +FROM + ( + SELECT + City, + Max(Cost) + FROM + SALES_FACT AS sf + INNER JOIN STORE AS s ON s.Store_key = sf.Store_key + ); + +-- 5. What was the least popular product brand? +SELECT + Brand as "Least Popular Brand" +FROM + ( + SELECT + Brand, + MIN(sales_sums) + FROM + ( + SELECT + p.Brand, + Sum(IfNull (Sales, 0)) AS sales_sums + FROM + SALES_FACT AS sf + RIGHT JOIN PRODUCT AS p ON sf.Product_key = p.Product_key + GROUP BY + p.Brand + ) + ); + +-- 6. Which city (or cities) sold "Sense and Sensibility"? +SELECT + City AS "City That Sold 'Sense and Sensibility'" +FROM + STORE AS s +WHERE + s.Store_key = ( + SELECT + sf.Store_key + FROM + SALES_FACT as sf + WHERE + sf.Product_key = ( + SELECT + p.Product_key + FROM + PRODUCT AS p + WHERE + p.Description = 'Sense and Sensibility' + ) + ); diff --git a/Spring-2023/CS-1011/Relational-DB-Assignment/solve.bash b/Spring-2023/CS-1011/Relational-DB-Assignment/solve.bash new file mode 100755 index 0000000..dbb401e --- /dev/null +++ b/Spring-2023/CS-1011/Relational-DB-Assignment/solve.bash @@ -0,0 +1,20 @@ +#!/usr/bin/env -S nix shell nixpkgs#bash nixpkgs#sqlite --command bash + +main() { + local count=1 + local double_answer=false + printf "Question Solutions\n" + printf "==================\n" + while IFS= read -r line; do + # This is an ugly hack, but I'm too lazy to do this "right". Question 4 has two possible + # answers based on your interpretation, thus I am outputting two answers for question 4 by + # doing this fugly stuff. + if ((count == 5)) && ! $double_answer; then + ((count--)) + double_answer=true + fi + printf "%d: %s\n" $((count++)) "${line}" + done < <(sqlite3 db.sqlite3 <./cmds.sql) +} + +main "${@}"