cs-1011: add solution to relational db assignment

This commit is contained in:
Price Hiller 2024-02-25 02:58:11 -06:00
parent 2c79f0bc12
commit ffa7c184d2
Signed by: Price
GPG Key ID: C3FADDE7A8534BEB
4 changed files with 259 additions and 0 deletions

View File

@ -0,0 +1 @@
*.sqlite3

View File

@ -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 |

View File

@ -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'
)
);

View File

@ -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 "${@}"