diff --git a/SQL_Code/Order_Generation.py b/SQL_Code/Order_Generation.py new file mode 100644 index 0000000..8355f35 --- /dev/null +++ b/SQL_Code/Order_Generation.py @@ -0,0 +1,317 @@ +#Outdated +#Run script: python3 scriptname.py +#password is the database password (pinned in discord) + +#To install dependencies: python3 -m pip install psycopg2-binary pandas numpy + +#Don't modify this file directly, copy it to a new script used for a specific task and modify from there + +import psycopg2 +import psycopg2.extras +import pandas as pd +import sys +import time +import datetime +import math +import random +import numpy as np + +#Generation Configuration +ORDERS_NEEDED = 1000000 #million +NUM_WEEKS = 52 +FUTURE_WEEKS = 2 +START_HOUR = 8 +CLOSE_HOUR = 20 #24 hour fomat +RUSH_DAY_MULTIPLIER = 10 #orders take on average x less time to come in + + +if len(sys.argv) < 2: + print("Arguments not recognized. \nUsage: python3 python_template.py ") + sys.exit() + +execute = False +if(len(sys.argv) > 2 and sys.argv[2] == "y"): + execute = True + +password = sys.argv[1] + +# Open output file +f = open("pythonGen.sql", "w") + +# Connect to an existing database +with psycopg2.connect("dbname=team_64_db user=team_64 password="+password+" host=csce-315-db.engr.tamu.edu") as conn: + # Open a cursor to perform database operations + with conn.cursor() as cur: + column_names_dict = {} + + #Helper functions + + #Ex: insert_row("Employees", (69, "Josh Colborn", "jcolborn@tamu.edu", "2147483647", "Drink Wizard")) + def insert_row(table, values): + column_names = column_names_dict[table] + values = [str(x) for x in values] + #print("Column names: {}\n".format(column_names)) + try: + insert_command_txt = "INSERT INTO " + table + " (" + ', '.join(column_names) + ") VALUES (" + ', '.join(values) + ");\n" + f.write(insert_command_txt) + if execute: + cur.execute( + "INSERT INTO " + table + " (" + ', '.join(column_names) + ") VALUES (" + ', '.join(['%s' for i in range(len(column_names))]) + ")", + values + ) + except Exception as e: + print("Error inserting: ", e) + print("All changes made before this will be discarded.") + conn.rollback() + + def insert_row_start(table): + column_names = column_names_dict[table] + insert_command_txt = "INSERT INTO " + table + " (" + ', '.join(column_names) + ") VALUES \n" + f.write(insert_command_txt) + + def insert_row_value(values): + values = [str(x) for x in values] + insert_command_txt = "(" + ', '.join(values) + ")\n" + f.write(insert_command_txt) + + def insert_row_end(): + f.write("\n") + + #Ex: print_col_names("Employees") + def print_col_info(table): + print("Column names and types for table " + table + ":") + + #Code from khampson's answer to https://stackoverflow.com/questions/27832289/postgresql-how-do-you-get-the-column-formats + cur2 = conn.cursor(cursor_factory=psycopg2.extras.DictCursor) + cur2.execute("""select * + from information_schema.columns + where table_schema NOT IN ('information_schema', 'pg_catalog') + order by table_name""") + + typeDict={} + for row in cur2: + if(row['table_name'] == table.lower()): + typeDict[row['column_name']] = row['data_type'] + + for col in column_names_dict[table]: #in correct order + print(col + ": " + typeDict[col]) + print('\n') + + + def get_dataframe(table): + cur.execute("SELECT * FROM " + table) + column_names = column_names_dict[table.lower()] + table = cur.fetchall() + + df = pd.DataFrame(table, columns=column_names) + df.set_index(column_names[0], inplace=True) + return(df) + + def get_dataframe_indexed(table): + cur.execute("SELECT * FROM " + table) + column_names = column_names_dict[table.lower()] + table = cur.fetchall() + + df = pd.DataFrame(table, columns=column_names) + #df.set_index(column_names[0], inplace=True) + return(df) + + def print_table(table): + print("Printing table " + table + ":") + df = get_dataframe(table) + if df.empty: + print('Table is empty.') + else: + print(df) + print('\n') + return(df) + + #Wipes all the data from a table + def wipe_table(table): + print("Wiping table " + table) + cur.execute("DELETE FROM " + table) + + #Returns a list of tables in the database + def get_tables(): + cur.execute("""SELECT table_name FROM information_schema.tables + WHERE table_schema = 'public'""") + return list(x[0] for x in cur.fetchall()) + + #Print list of tables in database + def print_tables(): + for table in get_tables(): + print(table) + + + #Returns strings containing values for drink, extras, and order. + def get_random_order_vals(order_id, order_date, final=False): + #num_drinks = max(int(np.random.normal(loc=1.5, scale=2)),1) + customer = customer_names[random.randint(0, len(customer_names)-1)] + employee_id = random.randint(0, 4)+1 #hard-coded cus it was messing up for some reason + total_price = 0 + drinks_string = "" + extras_string = "" + order_string = "" + + drink = drink_dt_indexed.iloc[random.randint(0, num_drinks-1)] + total_price += drink['drink_price'] + paymentMethodIndex = random.randint(0, 10) + paymentMethod="" + if(paymentMethodIndex == 0): + paymentMethod = "'Apple Pay'" + elif(paymentMethodIndex == 1): + paymentMethod = "'Gift Card'" + else: + paymentMethod = "'Credit Card'" + + + if(final): + rand_index = random.randint(0, num_extras-1) + extra = extras_dt_indexed.iloc[rand_index] + total_price += extra['extra_price'] + extras_string += "(" + str(order_id) + ", " + str(extra['extra_id']) + ");\n\n" + else: + num_extras_purchased = max(int(np.random.normal(loc=1.5, scale=1)),0) + indexes_chosen = [] + for i in range(num_extras_purchased): + rand_index = random.randint(0, num_extras-1) + if(rand_index not in indexes_chosen): + indexes_chosen.append(rand_index) + extra = extras_dt_indexed.iloc[rand_index] + total_price += extra['extra_price'] + extras_string += "(" + str(order_id) + ", " + str(extra['extra_id']) + "),\n" + + if(final): + drinks_string += "(" + str(order_id) + ", " + str(drink['drink_id']) + ");\n\n" + order_string += "(" + str(order_id) + ", '" + customer + "', " + str(total_price) + ", '" + order_date.strftime('%Y-%m-%d %H:%M:%S') + "', " + str(employee_id) + ", " + paymentMethod + ");\n\n" + else: + drinks_string += "(" + str(order_id) + ", " + str(drink['drink_id']) + "),\n" + order_string += "(" + str(order_id) + ", '" + customer + "', " + str(total_price) + ", '" + order_date.strftime('%Y-%m-%d %H:%M:%S') + "', " + str(employee_id) + ", " + paymentMethod + "),\n" + return((drinks_string, extras_string, order_string)) + + #returns of the datetime is a rush day + def isRushDay(day): + #August 19th for start of Fall (referencing Fall 2024) + FallStart = day.month == 8 and day.day == 19 + + #January 13th for start of Spring (referencing Spring 2025) + SpringStart = day.month == 1 and day.day == 13 + return(FallStart or SpringStart) + + #Get a list of column names for all tables so it doesn't need to be queried every time there's an insertion (way faster) + for table in get_tables(): + cur.execute("SELECT * FROM " + table) + column_names_dict[table] = [desc[0] for desc in cur.description] + #print_col_info(table) + #print_table(table) + + """ + Quick Reference: + print_table(table) + print_col_info(table) + insert_row(table, values) ex: insert_row("Employees", (69, "Josh Colborn", "jcolborn@tamu.edu", "2147483647", "Drink Wizard")) + wipe_table(table) + print_tables() + get_tables() + """ + #Your code here. Use helper functions to interact with the database. + + #To randomly select customer names + customer_names = [ + "Emma", "Liam", "Olivia", "Noah", "Ava", "Elijah", "Sophia", "James", + "Isabella", "Benjamin", "Mia", "Lucas", "Charlotte", "Mason", "Amelia", + "Ethan", "Harper", "Alexander", "Evelyn", "Henry", "Jack", "Ella", + "Daniel", "Scarlett", "Michael", "Grace", "Sebastian", "Lily", "Matthew", + "Aria", "Samuel", "Chloe", "David", "Mila", "Joseph", "Nora", "Carter", + "Hazel", "Owen", "Zoey", "Wyatt", "Riley", "John", "Victoria", "Luke", + "Penelope", "Gabriel", "Lillian", "Anthony", "Addison", "Dylan", "Layla", + "Isaac", "Natalie", "Grayson", "Hannah", "Leo", "Brooklyn", "Lincoln", + "Zoe", "Hudson", "Leah", "Hunter", "Audrey", "Nathan", "Savannah", + "Caleb", "Bella", "Eli", "Claire", "Connor", "Skylar", "Aaron", "Lucy", + "Landon", "Paisley", "Adrian", "Anna", "Jonathan", "Caroline", "Nolan", + "Genesis", "Jeremiah", "Aaliyah", "Easton", "Kennedy", "Elias", "Kinsley", + "Colton", "Aubrey", "Cameron", "Autumn", "Asher", "Sadie", "Dominic", + "Gabriella", "Axel", "Madelyn", "Jaxon", "Ariana", "Robert", "Stella", + "Maverick", "Allison", "Jose", "Ivy", "Everett", "Violet", "Parker", + "Lydia", "Xavier", "Elena", "Adam", "Naomi", "Jace", "Ruby" + ] + drink_dt = get_dataframe("drinks") + drink_dt_indexed = get_dataframe_indexed("drinks") + num_drinks = drink_dt.shape[0] + #print(num_drinks) + #print(drink_dt) + + extras_dt = get_dataframe("extras_and_toppings") + extras_dt_indexed = get_dataframe_indexed("extras_and_toppings") + num_extras= extras_dt.shape[0] + #print(num_extras) + #print(extras_dt) + + employees_dt = get_dataframe("employees") + employees_dt_indexed = get_dataframe_indexed("employees") + num_employees= employees_dt.shape[0] + + + + # Get start time for first day of business (52 weeks ago) + start_datetime = datetime.datetime.now() - datetime.timedelta(weeks=(NUM_WEEKS)) + start_datetime = start_datetime.replace(hour=START_HOUR, minute=0, second=0) + + order_id_global = 1 + + num_days = NUM_WEEKS*7 + FUTURE_WEEKS*7 + orders_per_day = math.ceil(ORDERS_NEEDED/num_days) + avg_time_between_orders = datetime.timedelta(hours = CLOSE_HOUR - START_HOUR)/orders_per_day + + + for currDay in range(num_days): + f.write("\n\n\n\n-- Day "+str(currDay)+'\n') + print("Day "+str(currDay)) + order_insertions_string = "INSERT INTO Orders(Order_ID, Customer, Order_total_price, Order_date, Employee_ID, Payment_method) VALUES\n" + order_items_insertions_string = "INSERT INTO Order_Items(Order_ID, Drink_ID) VALUES\n" + order_extra_insertions_string = "INSERT INTO Order_Extra(Order_ID, Extras_ID) VALUES\n" + + curr_time = start_datetime + datetime.timedelta(days=currDay) + + baseTimestep = avg_time_between_orders + if isRushDay(curr_time): + f.write("-- RUSH DAY!!!\n") + print("RUSH DAY!!!") + baseTimestep = baseTimestep/RUSH_DAY_MULTIPLIER + + while(curr_time.hour < CLOSE_HOUR): + #Returns strings containing values for drink, extras, and order. + orderVals = get_random_order_vals(order_id_global, curr_time) + order_items_insertions_string += orderVals[0] + order_extra_insertions_string += orderVals[1] + order_insertions_string += orderVals[2] + order_id_global+=1 + + curr_time += baseTimestep*random.random()*2 + + orderVals = get_random_order_vals(order_id_global, curr_time, final=True) + order_items_insertions_string += orderVals[0] + order_extra_insertions_string += orderVals[1] + order_insertions_string += orderVals[2] + order_id_global+=1 + + f.write(order_insertions_string + order_items_insertions_string + order_extra_insertions_string) + + + + + + + print("Orders per day requested: "+str(orders_per_day)) + print("Orders per day actual: "+str((order_id_global-1)/num_days)) + + + #print_table('orders') + #Decide whether to make changes or discard them + #saveChanges = input("Commit changes? (y/n): ") + #if saveChanges == "y": + # conn.commit() + #else: + # conn.rollback() + conn.rollback() +f.close() \ No newline at end of file diff --git a/SQL_Code/Seed_DB.sql b/SQL_Code/Seed_DB.sql new file mode 100644 index 0000000..7fc6f5e --- /dev/null +++ b/SQL_Code/Seed_DB.sql @@ -0,0 +1,9 @@ +\i delete_tables.sql +\i table_creation.sql + +\i bubbleflow_drinks.sql +\i bubbleflow_toppings_extras.sql +\i bubbleflow_ingredients.sql +\i bubbleflow_recipes.sql +\i bubbleflow_employees.sql +--\i bubbleflow_orders.sql \ No newline at end of file diff --git a/SQL_Code/bubbleflow_drinks.sql b/SQL_Code/bubbleflow_drinks.sql new file mode 100644 index 0000000..d16756e --- /dev/null +++ b/SQL_Code/bubbleflow_drinks.sql @@ -0,0 +1,45 @@ +insert into Drink_Categories(Drink_Category_ID, Drink_Category_NAME) values +(1, 'Milk Teas'), +(2, 'Brewed Tea'), +(3, 'Fruit Tea'), +(4, 'Fresh Milk'), +(5, 'Ice Blended'), +(6, 'Tea Mojito'), +(7, 'Creama'); + +insert into Drinks(Drink_ID, Drink_Category_ID, Drink_Name, Drink_Price) values +(001, 1, 'Classic Milk Tea', 4.75), +(002, 1, 'Honey Milk Tea', 4.85), +(003, 1, 'Classic Coffee', 4.85), +(004, 1, 'Ginger Milk Tea', 4.85), +(005, 1, 'Thai Pearl Milk Tea', 5.75), +(006, 1, 'Taro Pearl Milk Tea', 5.75), +(007, 2, 'Classic Tea', 4.25), +(008, 2, 'Wintermelon Tea', 4.25), +(009, 2, 'Honey Tea', 4.55), +(010, 2, 'Ginger Tea', 4.55), +(011, 3, 'Mango Green Tea', 5.75), +(012, 3, 'Wintermelon Lemonade', 5.75), +(013, 3, 'Strawberry Tea', 5.75), +(014, 3, 'Peach Tea with Aiyu Jelly', 5.75), +(015, 3, 'Kiwi Fruit Tea with Aiyu Jelly', 5.90), +(016, 3, 'Mango & Passion Fruit Tea', 5.90), +(017, 4, 'Cocoa Lover with Fresh Milk', 5.00), +(018, 4, 'Homemade Taro with Fresh Milk', 6.50), +(019, 4, 'Matcha with Fresh Milk', 5.15), +(020, 5, 'Oreo Ice Blended with Pearl', 6.75), +(021, 5, 'Matcha Red Bean Ice Blended with Ice Cream', 6.75), +(022, 5, 'Coffee Ice Blended with Ice Cream', 6.75), +(023, 5, 'Mango Ice Blended with Ice Cream', 6.75), +(024, 5, 'Strawberry Ice Blended with Lychee Jelly & Ice Cream', 6.75), +(025, 6, 'Lime Mojito', 6.00), +(026, 6, 'Mango Mojito', 6.00), +(027, 6, 'Peach Mojito', 6.00), +(028, 6, 'Strawberry Mojito', 6.00), +(029, 7, 'Creama Tea', 6.00), +(030, 7, 'Match Creama', 6.00), +(031, 7, 'Coffee Creama', 6.15), +(032, 7, 'Cocoa Creama', 6.50); + +-- select * from Drinks; +-- select * from Drink_Categories; \ No newline at end of file diff --git a/SQL_Code/bubbleflow_employees.sql b/SQL_Code/bubbleflow_employees.sql new file mode 100644 index 0000000..87784a8 --- /dev/null +++ b/SQL_Code/bubbleflow_employees.sql @@ -0,0 +1,8 @@ +insert into Employees(Employee_ID, Employee_Name, Employee_Email, Employee_Phone, Employee_Position) values +(1,'Sophia Phu','sophiaaphu@tamu.edu', '(555) 374-9201', 'The Overseer (Manager)'), +(2,'Abhisri Dasari','abhisri.dasari@tamu.edu', '(555) 333-8527', 'Counting Keeper (Cashier)'), +(3,'Josh Colborn','h.donkins2@gmail.com', '(555) 520-1789', 'Drink Wizard (Bartender)'), +(4,'Luke Crittell','lccrittell@gmail.com', '(555) 904-6721', 'Counting Keeper (Cashier)'), +(5,'Cameron Stone','cameron28202@gmail.com', '(555) 134-8679', 'Spellmaster (Waiter)'); + +-- select * from Employees; \ No newline at end of file diff --git a/SQL_Code/bubbleflow_ingredients.sql b/SQL_Code/bubbleflow_ingredients.sql new file mode 100644 index 0000000..bfb8ba4 --- /dev/null +++ b/SQL_Code/bubbleflow_ingredients.sql @@ -0,0 +1,54 @@ +--ingredient_categories removed +--insert into Ingredient_Categories(Ingredient_Category_ID, Ingredient_Category_NAME) values +--(1, 'Tea Base'), +--(2, 'Dairy'), +--(3, 'Flavor Powder'), +--(4, 'Fruit'), +--(5, 'Sweeteners'), +--(6, 'Ice'), +--(7, 'Topping'); + +-- Insert statements for the Inventory table +INSERT INTO Inventory (Item_ID, Item_Name, Item_Metric, Item_Quantity) VALUES (1, 'Green Tea Base', 'kilograms', 23.5), +(2, 'Oolong Tea Base', 'kilograms', 15.0), +(3, 'Black Tea Base', 'kilograms', 50.25), +(4, 'Thai Tea Base', 'kilograms', 50.25), +(5, 'Milk Powder', 'kilograms', 40.0), +(6, 'Fresh Milk', 'liters', 10.0), +(7, 'Lime Juice', 'liters', 5.0), +(8, 'Brown Sugar Syrup', 'liters', 12.0), +(9, 'Mango Syrup', 'liters', 10.0), +(10, 'Strawberry Syrup', 'liters', 8.0), +(11, 'Wintermelon Syrup', 'liters', 8.0), +(12, 'Peach Syrup', 'liters', 8.0), +(13, 'Kiwi Syrup', 'liters', 8.0), +(14, 'Passion Fruit Syrup', 'liters', 8.0), +(15, 'Ginger Syrup', 'liters', 8.0), +(16, 'Honey', 'liters', 15.7), +(17, 'Sugar', 'kilograms', 14.7), +(18, 'Matcha Powder', 'kilograms', 20.0), +(19, 'Cofee Powder', 'kilograms', 23.0), +(20, 'Coco Powder', 'kilograms', 23.0), +(21, 'Taro Powder', 'kilograms', 18.0), +(22, 'Oreos', 'kilograms', 11.0), +(23, 'Mint Leaves', 'kilograms', 5.0), +(24, 'Pearl', 'kilograms', 12.0), +(25, 'Mini Pearl', 'kilograms', 10.0), +(26, 'Ice Cream', 'kilograms', 17.0), +(27, 'Pudding', 'kilograms', 15.6), +(28, 'Aloe Vera', 'kilograms', 23.5), +(29, 'Red Beans', 'kilograms', 18.6), +(30, 'Herb Jelly', 'kilograms', 19.2), +(31, 'Aiyu Jelly', 'kilograms', 23.4), +(32, 'Lychee Jelly', 'kilograms', 22.5), +(33, 'Creama', 'kilograms', 14.7), +(34, 'Ice', 'cups', 14.7), +(35, 'Water', 'liters', 20), +(36, 'Cups', 'cups', 400), +(37, 'Lids', 'lids', 400), +(38, 'Straws', 'straws', 400), +(39, 'Napkins', 'napkins', 400), +(40, 'Straws', 'bags', 400); + +--Insert statements for the Ingredients table +--removed \ No newline at end of file diff --git a/SQL_Code/bubbleflow_queries_abhi.sql b/SQL_Code/bubbleflow_queries_abhi.sql new file mode 100644 index 0000000..c75361e --- /dev/null +++ b/SQL_Code/bubbleflow_queries_abhi.sql @@ -0,0 +1,98 @@ +-- Special Query #4: "Menu Item Inventory" +-- select count of inventory items from inventory and menu grouped by menu item +-- given a specific menu item, how many items from the inventory does that menu item use? +-- DESCENDING ORDER WITH DRINKS THAT USE THE MOST ITEMS AT THE TOP +select + Drinks.Drink_ID, + Drinks.Drink_Name, + count(Drink_Recipe.Ingredient_ID) as Ingredients_Used +from Drinks +join Drink_Recipe + on Drinks.Drink_ID = Drink_Recipe.Drink_ID +group by Drinks.Drink_ID, Drinks.Drink_Name +-- order by Drinks.Drink_ID asc; +order by Ingredients_Used desc; + + +-- Query #1: "Core Ingredients" +-- From each ingredient category, find the ingredient that is used in the most drinks? +with drink_per_ingredient as ( + -- connect between the ingredients table and the drink_recipes table using Ingredient_ID + -- then, group by the Ingredient_Category_ID + select + Ingredients.Ingredient_ID, + Ingredients.Ingredient_Category_ID, + Ingredients.Item_ID, + count(Drink_Recipe.Drink_ID) as Used_by_Number_of_Drinks + -- Drink_Recipe.Drink_ID as dr_d_id + -- count(Drink_ID) as drink_usage + from Ingredients + -- join Inventory +-- on Ingredients.Item_ID = Inventory.Item_ID + join Drink_Recipe + on Ingredients.Ingredient_ID = Drink_Recipe.Ingredient_ID + group by Ingredients.Ingredient_ID, Ingredients.Ingredient_Category_ID +) + +select + dpi.Ingredient_Category_ID, + ic.Ingredient_Category_NAME, + dpi.Ingredient_ID, + inv.Item_Name, + dpi.Used_by_Number_of_Drinks +from drink_per_ingredient dpi -- retrive data from the "function" above + join ( + select + Ingredient_Category_ID, + max(Used_by_Number_of_Drinks) as max_u + from drink_per_ingredient + group by Ingredient_Category_ID + -- only select the ingredient that is used by most drinks from each ingredient category + ) max_used + on dpi.Ingredient_Category_ID = max_used.Ingredient_Category_ID + and dpi.Used_by_Number_of_Drinks = max_used.max_u + -- below lets u create a column with the ingredient category name + join Ingredient_Categories ic + on ic.Ingredient_Category_ID = dpi.Ingredient_Category_ID + -- below lets u create a column with the ingredient name + -- note that the name of the ingredient had to be retrieved from invetory via Item_ID tag + join Inventory inv + on dpi.Ingredient_ID = inv.Item_ID + -- order by ic.Ingredient_Category_Name; + order by dpi.Ingredient_Category_ID asc; + + +-- Query #3: "Low Stock in Inventory" +-- Identify which ingredients are running low in inventory (less than 10 units) & order by Item_ID +select + Item_ID, + Item_Name as Item_Running_Low, + Item_Quantity as Units_Left +from Inventory +where Item_Quantity < 10.0 +order by Item_ID asc; + +-- Query #4: "Free extra & toppings" +select + ec.Extra_Category_ID, + ec.Extra_Category_NAME, + -- for each category there is a sum (intially set to 0), everytime a price = 0.00 (free), the sum increments by 1 + -- the sum for each category is return at the end + sum(case when et.Extra_Price = 0.00 then 1 when et.Extra_Price != 0.00 then 0 end) as Free_items + -- et.Extra_Price + from Extras_Categories ec + left join Extras_and_Toppings et + on ec.Extra_Category_ID = et.Extra_Category_ID + -- where et.Extra_Price = 0.00 + group by ec.Extra_Category_ID, ec.Extra_Category_NAME + order by ec.Extra_Category_ID asc; + +-- select * from Drinks; +-- select * from Drink_Categories; +-- select * from Extras_Categories; +-- select * from Extras_and_Toppings; +-- select * from Employees; +-- select * from Ingredient_Categories; +-- select * from Inventory; +-- select * from Ingredients; +-- select * from Drink_Recipe; diff --git a/SQL_Code/bubbleflow_query_luke.sql b/SQL_Code/bubbleflow_query_luke.sql new file mode 100644 index 0000000..a4c4869 --- /dev/null +++ b/SQL_Code/bubbleflow_query_luke.sql @@ -0,0 +1,69 @@ + +/*Special Query 2 +Special Query #2: "Realistic Sales History" + + pseudocode: select count of orders, sum of order total grouped by hour + about: given a specific hour of the day, how many orders were placed and what was the total sum of the orders? + example: e.g., "12pm has 12345 orders totaling $86753"*/ + +SELECT + EXTRACT(HOUR FROM order_date) as hour_num, --Hour extraction + COUNT(*) as order_count, --Total the number of orders + SUM(order_total_price) as total_sales --Sum the cost of the orders +FROM orders +GROUP BY + EXTRACT(HOUR FROM order_date) --Group by hour +ORDER BY + hour_num; --Go hour by hour + +/*Special Query 3 +Special Query #3: "Peak Sales Day" + + pseudocode: select top 10 sums of order total grouped by day in descending order by order total + about: given a specific day, what was the sum of the top 10 order totals? + example: "30 August has $12345 of top sales" +*/ +SELECT + EXTRACT(YEAR FROM order_date) as order_year, --Order year + EXTRACT(MONTH FROM order_date) as order_month, --Order month + EXTRACT(DAY FROM order_date) as order_day, --Order day + SUM(order_total_price) as total_sales --Sum the sales +FROM orders +GROUP BY + order_year, order_month, order_day --Group to find individual days +ORDER BY + total_sales DESC --Order by sales to get highest sales, make sure DESC to have the higest 10 first +LIMIT 10; --Limit to top 10 + + + +--Query 5; gets the top ten most expensive drinks on the menu +SELECT drink_name,drink_price FROM drinks ORDER BY drink_price DESC LIMIT 10; + +--Query 6; get total revenue plus tax +SELECT + SUM(order_total_price * 1.0825) as total_rev_with_tax --this works apparently +FROM + orders; +--Query 11; Average Drink Price for each drink category +SELECT + drink_category_id as category, --Get category id + AVG(drink_cost) as avg_cost --average the cost of each category +FROM drinks +GROUP BY + drink_category_id --Group by the id +ORDER BY + drink_category_id; --Order by groups + +--Query 12; Most popular toppings, returns extras ID and price sorted by most expensive +SELECT + order_extra.extras_id as extras_id, + SUM(order_extra.extras_id) as total_extras +FROM order_extra +GROUP BY + extras_id +ORDER BY + total_extras DESC; + +--Query 13; List employee names and emails for communication +SELECT employee_name as name, employee_email as email FROM employees; diff --git a/SQL_Code/bubbleflow_recipes.sql b/SQL_Code/bubbleflow_recipes.sql new file mode 100644 index 0000000..482982f --- /dev/null +++ b/SQL_Code/bubbleflow_recipes.sql @@ -0,0 +1,108 @@ +-- Insert statements for Drink_Recipe +INSERT INTO Drink_Recipe (Drink_ID, Item_ID, Quantity_Used) VALUES (1, 3, 0.08), +(1, 5, 0.015), +(1, 17, 0.01), +(1, 35, 0.2), +(2, 3, 0.008), +(2, 5, 0.015), +(2, 16, 0.005), +(2, 35, 0.2), +(3, 19, 0.005), +(3, 5, 0.015), +(3, 17, 0.01), +(3, 35, 0.2), +(4, 3, 0.008), +(4, 5, 0.015), +(4, 15, 0.005), +(4, 35, 0.2), +(5, 4, 0.008), +(5, 5, 0.015), +(5, 24, 0.03), +(5, 35, 0.2), +(6, 21, 0.01), +(6, 5, 0.015), +(6, 24, 0.03), +(6, 35, 0.2), +(7, 3, 0.008), +(7, 35, 0.2), +(8, 11, 0.01), +(8, 35, 0.2), +(9, 3, 0.008), +(9, 16, 0.005), +(9, 35, 0.2), +(10, 3, 0.008), +(10, 15, 0.005), +(10, 35, 0.2), +(11, 1, 0.008), +(11, 9, 0.01), +(11, 35, 0.2), +(12, 11, 0.01), +(12, 7, 0.01), +(12, 35, 0.2), +(13, 3, 0.008), +(13, 10, 0.01), +(13, 35, 0.2), +(14, 3, 0.008), +(14, 12, 0.01), +(14, 31, 0.015), +(14, 35, 0.2), +(15, 3, 0.008), +(15, 13, 0.01), +(15, 31, 0.015), +(15, 35, 0.2), +(16, 3, 0.008), +(16, 9, 0.01), +(16, 14, 0.01), +(16, 35, 0.2), +(17, 20, 0.005), +(17, 6, 0.2), +(17, 17, 0.01), +(17, 35, 0.2), +(18, 21, 0.01), +(18, 6, 0.2), +(18, 17, 0.01), +(18, 35, 0.2), +(19, 18, 0.005), +(19, 6, 0.2), +(19, 17, 0.01), +(20, 22, 0.005), +(20, 24, 0.03), +(20, 26, 0.02), +(21, 18, 0.005), +(21, 29, 0.015), +(21, 26, 0.02), +(21, 34, 1), +(22, 19, 0.005), +(22, 26, 0.02), +(22, 34, 1), +(23, 9, 0.01), +(23, 26, 0.02), +(23, 34, 1), +(24, 10, 0.01), +(24, 32, 0.015), +(24, 26, 0.02), +(24, 34, 1), +(25, 7, 0.01), +(25, 23, 0.002), +(25, 35, 0.2), +(26, 9, 0.01), +(26, 23, 0.002), +(26, 35, 0.2), +(27, 12, 0.01), +(27, 23, 0.002), +(27, 35, 0.2), +(28, 10, 0.01), +(28, 23, 0.002), +(28, 35, 0.2), +(29, 3, 0.008), +(29, 33, 0.02), +(29, 35, 0.2), +(30, 18, 0.005), +(30, 33, 0.02), +(30, 35, 0.2), +(31, 19, 0.005), +(31, 33, 0.02), +(31, 35, 0.2), +(32, 20, 0.005), +(32, 33, 0.02), +(32, 35, 0.2); diff --git a/SQL_Code/bubbleflow_toppings_extras.sql b/SQL_Code/bubbleflow_toppings_extras.sql new file mode 100644 index 0000000..7145741 --- /dev/null +++ b/SQL_Code/bubbleflow_toppings_extras.sql @@ -0,0 +1,28 @@ +insert into Extras_Categories(Extra_Category_ID, Extra_Category_NAME) values +(1, 'Ice Level'), +(2, 'Sweetness Level'), +(3, 'Toppings'); + +insert into Extras_and_Toppings(Extra_ID, Extra_Category_ID, Extra_Name, Extra_Price) values +(001, 1, 'Regular Ice', 0.00), +(002, 1, 'Less Ice', 0.00), +(003, 1, 'No Ice', 0.00), +(004, 2, 'Extra Sweet 120%', 0.00), +(005, 2, 'Normal 100%', 0.00), +(006, 2, 'Less 80%', 0.00), +(007, 2, 'Half 50%', 0.00), +(008, 2, 'Light 0%', 0.00), +(009, 2, 'No Sugar 0%', 0.00), +(010, 3, 'Pearl', 0.75), +(011, 3, 'Mini Pearl', 0.75), +(012, 3, 'Ice Cream', 0.75), +(013, 3, 'Pudding', 0.75), +(014, 3, 'Aloe Vera', 0.75), +(015, 3, 'Red Beans', 0.75), +(016, 3, 'Herb Jelly', 0.75), +(017, 3, 'Aiyu Jelly', 0.75), +(018, 3, 'Lychee Jelly', 0.75), +(019, 3, 'Creama', 1.00); + +-- select * from Extras_Categories; +-- select * from Extras_and_Toppings; \ No newline at end of file diff --git a/SQL_Code/bubleflow_queries_cam.sql b/SQL_Code/bubleflow_queries_cam.sql new file mode 100644 index 0000000..d3603e0 --- /dev/null +++ b/SQL_Code/bubleflow_queries_cam.sql @@ -0,0 +1,99 @@ +-- Special Query #1: "Weekly Sales History" +-- pseudocode: select count of orders grouped by week +-- about: given a specific week, how many orders were placed? +-- example: "week 1 has 98765 orders" +SELECT + EXTRACT(WEEK FROM order_date) as week_number, + COUNT(*) as order_count, + SUM(order_total_price) as total_sales +FROM orders +GROUP BY + EXTRACT(WEEK FROM order_date) +ORDER BY + week_number; + +-- Query 8 +-- drinks that generate the most revenue +-- order drinks from most revenue to least revenue + +SELECT + d.drink_name as drink_name, + COUNT(*) as times_ordered, + SUM(o.order_total_price) as total_revenue +FROM orders o +JOIN order_items oi ON o.order_id = oi.order_id +JOIN drinks d ON oi.drink_id = d.drink_id +GROUP BY d.drink_name +ORDER BY total_revenue DESC; + + +-- Query #7 +-- most popular drinks +-- order drinks descending by count + +SELECT + d.drink_name as drink_name, + COUNT(*) as times_ordered +FROM orders o +JOIN order_items oi ON o.order_id = oi.order_id +JOIN drinks d ON oi.drink_id = d.drink_id +GROUP BY d.drink_name +ORDER BY times_ordered DESC; + +-- Query #2 +-- orders processed by employee X +-- how many orders are processed by said employee? + +SELECT + e.employee_name as employee_name, + COUNT(*) as number_orders, + SUM(o.order_total_price) as total_revenue +FROM orders o +JOIN employees e ON o.employee_id = e.employee_id +GROUP BY e.employee_name +ORDER BY number_orders DESC; + + +-- Query 9 +-- group orders by hour +-- sort descending to show which hours have least orders/revenue +-- useful to set store hours for only good hours + +SELECT + EXTRACT(HOUR FROM order_date) as hour_number, + SUM(o.order_total_price) as total_revenue +FROM orders o +GROUP BY hour_number +ORDER BY total_revenue DESC; + + +-- Query 10 +-- find total sales revenue + +SELECT + SUM(o.order_total_price) as total_revenue +FROM orders o + +-- Query 14 +-- Most Loyal Customer +-- List customers descending by how many drinks they have ordered + +SELECT + customer as customer_name, + COUNT(*) as times_visited +FROM orders o +GROUP BY customer_name +ORDER BY times_visited DESC; + +-- Query 15 +-- Most Extra Drinks +-- List the drinks that most often have toppings / extras added to them + +SELECT + d.drink_name, + COUNT(*) as total_extras_count +FROM drinks d +JOIN order_items oi ON d.drink_id = oi.drink_id +JOIN order_extra oe ON oi.order_id = oe.order_id +GROUP BY d.drink_name +ORDER BY total_extras_count DESC; \ No newline at end of file diff --git a/SQL_Code/delete_tables.sql b/SQL_Code/delete_tables.sql new file mode 100644 index 0000000..0a3fd8c --- /dev/null +++ b/SQL_Code/delete_tables.sql @@ -0,0 +1,12 @@ +DROP TABLE IF EXISTS Drink_Categories CASCADE; +DROP TABLE IF EXISTS Drinks CASCADE; +DROP TABLE IF EXISTS Extras_Categories CASCADE; +DROP TABLE IF EXISTS Extras_and_Toppings CASCADE; +DROP TABLE IF EXISTS Ingredient_Categories CASCADE; +DROP TABLE IF EXISTS Inventory CASCADE; +DROP TABLE IF EXISTS Ingredients CASCADE; +DROP TABLE IF EXISTS Drink_Recipe CASCADE; +DROP TABLE IF EXISTS Employees CASCADE; +DROP TABLE IF EXISTS Orders CASCADE; +DROP TABLE IF EXISTS Order_Items CASCADE; +DROP TABLE IF EXISTS Order_Extra CASCADE; \ No newline at end of file diff --git a/SQL_Code/normal_query.sql b/SQL_Code/normal_query.sql new file mode 100644 index 0000000..98ff825 --- /dev/null +++ b/SQL_Code/normal_query.sql @@ -0,0 +1,204 @@ +--List of normal Queries, ordered by number on UML diagram + +-- Query #1: "Core Ingredients" +-- From each ingredient category, find the ingredient that is used in the most drinks? +with drink_per_ingredient as ( + -- connect between the ingredients table and the drink_recipes table using Ingredient_ID + -- then, group by the Ingredient_Category_ID + select + Ingredients.Ingredient_ID, + Ingredients.Ingredient_Category_ID, + Ingredients.Item_ID, + count(Drink_Recipe.Drink_ID) as Used_by_Number_of_Drinks + -- Drink_Recipe.Drink_ID as dr_d_id + -- count(Drink_ID) as drink_usage + from Ingredients + -- join Inventory +-- on Ingredients.Item_ID = Inventory.Item_ID + join Drink_Recipe + on Ingredients.Ingredient_ID = Drink_Recipe.Ingredient_ID + group by Ingredients.Ingredient_ID, Ingredients.Ingredient_Category_ID +) + +select + dpi.Ingredient_Category_ID, + ic.Ingredient_Category_NAME, + dpi.Ingredient_ID, + inv.Item_Name, + dpi.Used_by_Number_of_Drinks +from drink_per_ingredient dpi -- retrive data from the "function" above + join ( + select + Ingredient_Category_ID, + max(Used_by_Number_of_Drinks) as max_u + from drink_per_ingredient + group by Ingredient_Category_ID + -- only select the ingredient that is used by most drinks from each ingredient category + ) max_used + on dpi.Ingredient_Category_ID = max_used.Ingredient_Category_ID + and dpi.Used_by_Number_of_Drinks = max_used.max_u + -- below lets u create a column with the ingredient category name + join Ingredient_Categories ic + on ic.Ingredient_Category_ID = dpi.Ingredient_Category_ID + -- below lets u create a column with the ingredient name + -- note that the name of the ingredient had to be retrieved from invetory via Item_ID tag + join Inventory inv + on dpi.Ingredient_ID = inv.Item_ID + -- order by ic.Ingredient_Category_Name; + order by dpi.Ingredient_Category_ID asc; + + +-- Query #2 +-- orders processed by employee X +-- how many orders are processed by said employee? + +SELECT + e.employee_name as employee_name, + COUNT(*) as number_orders, + SUM(o.order_total_price) as total_revenue +FROM orders o +JOIN employees e ON o.employee_id = e.employee_id +GROUP BY e.employee_name +ORDER BY number_orders DESC; + + +-- Query #3: "Low Stock in Inventory" +-- Identify which ingredients are running low in inventory (less than 10 units) & order by Item_ID +select + Item_ID, + Item_Name as Item_Running_Low, + Item_Quantity as Units_Left +from Inventory +where Item_Quantity < 10.0 +order by Item_ID asc; + + +-- Query #4: "Free extra & toppings" +select + ec.Extra_Category_ID, + ec.Extra_Category_NAME, + -- for each category there is a sum (intially set to 0), everytime a price = 0.00 (free), the sum increments by 1 + -- the sum for each category is return at the end + sum(case when et.Extra_Price = 0.00 then 1 when et.Extra_Price != 0.00 then 0 end) as Free_items + -- et.Extra_Price + from Extras_Categories ec + left join Extras_and_Toppings et + on ec.Extra_Category_ID = et.Extra_Category_ID + -- where et.Extra_Price = 0.00 + group by ec.Extra_Category_ID, ec.Extra_Category_NAME + order by ec.Extra_Category_ID asc; + + +--Query 5; gets the top ten most expensive drinks on the menu +SELECT drink_name,drink_price FROM drinks ORDER BY drink_price DESC LIMIT 10; + + + +--Query 6; get total revenue plus tax +SELECT + SUM(order_total_price * 1.0825) as total_rev_with_tax --this works apparently +FROM + orders; + + +-- Query #7 +-- most popular drinks +-- order drinks descending by count + +SELECT + d.drink_name as drink_name, + COUNT(*) as times_ordered +FROM orders o +JOIN order_items oi ON o.order_id = oi.order_id +JOIN drinks d ON oi.drink_id = d.drink_id +GROUP BY d.drink_name +ORDER BY times_ordered DESC; + + +-- Query 8 +-- drinks that generate the most revenue +-- order drinks from most revenue to least revenue + +SELECT + d.drink_name as drink_name, + COUNT(*) as times_ordered, + SUM(o.order_total_price) as total_revenue +FROM orders o +JOIN order_items oi ON o.order_id = oi.order_id +JOIN drinks d ON oi.drink_id = d.drink_id +GROUP BY d.drink_name +ORDER BY total_revenue DESC; + + +-- Query 9 +-- group orders by hour +-- sort descending to show which hours have least orders/revenue +-- useful to set store hours for only good hours + +SELECT + EXTRACT(HOUR FROM order_date) as hour_number, + SUM(o.order_total_price) as total_revenue +FROM orders o +GROUP BY hour_number +ORDER BY total_revenue DESC; + + +-- Query 10 +-- find total sales revenue + +SELECT + SUM(orders.order_total_price) as total_revenue +FROM orders; + + +--Query 11; Average Drink Price for each drink category +SELECT + drink_category_id as category, --Get category id + AVG(Drink_Price) as avg_cost --average the cost of each category +FROM drinks +GROUP BY + drink_category_id --Group by the id +ORDER BY + drink_category_id; --Order by groups + + + +--Query 12; Most popular toppings, returns extras ID and price sorted by most expensive +SELECT + order_extra.extras_id as extras_id, + SUM(order_extra.extras_id) as total_extras +FROM order_extra +GROUP BY + extras_id +ORDER BY + total_extras DESC; + + +--Query 13; List employee names and emails for communication +SELECT employee_name as name, employee_email as email FROM employees; + + +-- Query 14 +-- Most Loyal Customer +-- List customers descending by how many drinks they have ordered + +SELECT + customer as customer_name, + COUNT(*) as times_visited +FROM orders o +GROUP BY customer_name +ORDER BY times_visited DESC; + + +-- Query 15 +-- Most Extra Drinks +-- List the drinks that most often have toppings / extras added to them + +SELECT + d.drink_name, + COUNT(*) as total_extras_count +FROM drinks d +JOIN order_items oi ON d.drink_id = oi.drink_id +JOIN order_extra oe ON oi.order_id = oe.order_id +GROUP BY d.drink_name +ORDER BY total_extras_count DESC; diff --git a/SQL_Code/recipe_creation.py b/SQL_Code/recipe_creation.py new file mode 100644 index 0000000..6a6c21c --- /dev/null +++ b/SQL_Code/recipe_creation.py @@ -0,0 +1,130 @@ +#Outdated +def generate_drink_recipes(output_file): + boba_recipe_items = { + "Green Tea Base": 1, + "Oolong Tea Base": 2, + "Black Tea Base": 3, + "Thai Tea Base": 4, + "Milk Powder": 5, + "Fresh Milk": 6, + "Lime Juice": 7, + "Brown Sugar Syrup": 8, + "Mango Syrup": 9, + "Strawberry Syrup": 10, + "Wintermelon Syrup": 11, + "Peach Syrup": 12, + "Kiwi Syrup": 13, + "Passion Fruit Syrup": 14, + "Ginger Syrup": 15, + "Honey": 16, + "Sugar": 17, + "Matcha Powder": 18, + "Cofee Powder": 19, + "Coco Powder": 20, + "Taro Powder": 21, + "Oreos": 22, + "Mint Leaves": 23, + "Pearl": 24, + "Mini Pearl": 25, + "Ice Cream": 26, + "Pudding": 27, + "Aloe Vera": 28, + "Red Beans": 29, + "Herb Jelly": 30, + "Aiyu Jelly": 31, + "Lychee Jelly": 32, + "Creama": 33, + "Ice": 34, + "Water": 35 + } + + drinks_list = [ + (1, 'Classic Milk Tea'), + (2, 'Honey Milk Tea'), + (3, 'Classic Coffee'), + (4, 'Ginger Milk Tea'), + (5, 'Thai Pearl Milk Tea'), + (6, 'Taro Pearl Milk Tea'), + (7, 'Classic Tea'), + (8, 'Wintermelon Tea'), + (9, 'Honey Tea'), + (10, 'Ginger Tea'), + (11, 'Mango Green Tea'), + (12, 'Wintermelon Lemonade'), + (13, 'Strawberry Tea'), + (14, 'Peach Tea with Aiyu Jelly'), + (15, 'Kiwi Fruit Tea with Aiyu Jelly'), + (16, 'Mango & Passion Fruit Tea'), + (17, 'Cocoa Lover with Fresh Milk'), + (18, 'Homemade Taro with Fresh Milk'), + (19, 'Matcha with Fresh Milk'), + (20, 'Oreo Ice Blended with Pearl'), + (21, 'Matcha Red Bean Ice Blended with Ice Cream'), + (22, 'Coffee Ice Blended with Ice Cream'), + (23, 'Mango Ice Blended with Ice Cream'), + (24, 'Strawberry Ice Blended with Lychee Jelly & Ice Cream'), + (25, 'Lime Mojito'), + (26, 'Mango Mojito'), + (27, 'Peach Mojito'), + (28, 'Strawberry Mojito'), + (29, 'Creama Tea'), + (30, 'Match Creama'), + (31, 'Coffee Creama'), + (32, 'Cocoa Creama') + ] + + #map drink id to its ingredients + drink_to_ingredients = { + 1: ["Black Tea Base", "Milk Powder", "Sugar", "Water"], # Classic Milk Tea + 2: ["Black Tea Base", "Milk Powder", "Honey", "Water"], # Honey Milk Tea + 3: ["Cofee Powder", "Milk Powder", "Sugar", "Water"], # Classic Coffee + 4: ["Black Tea Base", "Milk Powder", "Ginger Syrup", "Water"], # Ginger Milk Tea + 5: ["Thai Tea Base", "Milk Powder", "Pearl", "Water"], # Thai Pearl Milk Tea + 6: ["Taro Powder", "Milk Powder", "Pearl", "Water"], # Taro Pearl Milk Tea + 7: ["Black Tea Base", "Water"], # Classic Tea + 8: ["Wintermelon Syrup", "Water"], # Wintermelon Tea + 9: ["Black Tea Base", "Honey", "Water"], # Honey Tea + 10: ["Black Tea Base", "Ginger Syrup", "Water"], # Ginger Tea + 11: ["Green Tea Base", "Mango Syrup", "Water",], # Mango Green Tea + 12: ["Wintermelon Syrup", "Lime Juice", "Water"], # Wintermelon Lemonade + 13: ["Black Tea Base", "Strawberry Syrup", "Water"], # Strawberry Tea + 14: ["Black Tea Base", "Peach Syrup", "Aiyu Jelly", "Water"], # Peach Tea with Aiyu Jelly + 15: ["Black Tea Base", "Kiwi Syrup", "Aiyu Jelly", "Water"], # Kiwi Fruit Tea with Aiyu Jelly + 16: ["Black Tea Base", "Mango Syrup", "Passion Fruit Syrup", "Water"], # Mango & Passion Fruit Tea + 17: ["Coco Powder", "Fresh Milk", "Sugar", "Water"], # Cocoa Lover with Fresh Milk + 18: ["Taro Powder", "Fresh Milk", "Sugar", "Water"], # Homemade Taro with Fresh Milk + 19: ["Matcha Powder", "Fresh Milk", "Sugar"], # Matcha with Fresh Milk + 20: ["Oreos", "Pearl", "Ice Cream"], # Oreo Ice Blended with Pearl + 21: ["Matcha Powder", "Red Beans", "Ice Cream", "Ice"], # Matcha Red Bean Ice Blended with Ice Cream + 22: ["Cofee Powder", "Ice Cream","Ice"], # Coffee Ice Blended with Ice Cream + 23: ["Mango Syrup", "Ice Cream","Ice"], # Mango Ice Blended with Ice Cream + 24: ["Strawberry Syrup", "Lychee Jelly", "Ice Cream", "Ice"], # Strawberry Ice Blended with Lychee Jelly & Ice Cream + 25: ["Lime Juice", "Mint Leaves", "Water"], # Lime Mojito + 26: ["Mango Syrup", "Mint Leaves", "Water"], # Mango Mojito + 27: ["Peach Syrup", "Mint Leaves", "Water"], # Peach Mojito + 28: ["Strawberry Syrup", "Mint Leaves", "Water"], # Strawberry Mojito + 29: ["Black Tea Base", "Creama", "Water"], # Creama Tea + 30: ["Matcha Powder", "Creama", "Water"], # Match Creama + 31: ["Cofee Powder", "Creama", "Water"], # Coffee Creama + 32: ["Coco Powder", "Creama", "Water"] # Cocoa Creama + } + + with open(output_file, "w") as sql_file: + sql_file.write("-- Insert statements for Drink_Recipe\n") + + for (drink_id, drink_name) in drinks_list: + if drink_id in drink_to_ingredients: + for ing_name in drink_to_ingredients[drink_id]: + if ing_name in boba_recipe_items: + ingredient_id = boba_recipe_items[ing_name] + insert_stmt = ( + f"INSERT INTO Drink_Recipe (Drink_ID, Ingredient_ID) " + f"VALUES ({drink_id}, {ingredient_id});\n" + ) + sql_file.write(insert_stmt) + else: + # If the ingredient isn't found, you can decide to skip or raise an error + sql_file.write(f"-- WARNING: Ingredient '{ing_name}' not found for Drink ID {drink_id}\n") + +output_filename = "bubbleflow_recipes.sql" +generate_drink_recipes(output_filename) diff --git a/SQL_Code/special_query.sql b/SQL_Code/special_query.sql new file mode 100644 index 0000000..f207543 --- /dev/null +++ b/SQL_Code/special_query.sql @@ -0,0 +1,70 @@ +-- Special Query #1: "Weekly Sales History" +-- pseudocode: select count of orders grouped by week +-- about: given a specific week, how many orders were placed? +-- example: "week 1 has 98765 orders" +SELECT + EXTRACT(WEEK FROM order_date) as week_number, + COUNT(*) as order_count, + SUM(order_total_price) as total_sales +FROM orders +GROUP BY + EXTRACT(WEEK FROM order_date) +ORDER BY + week_number; + + + +/*Special Query 2 +Special Query #2: "Realistic Sales History" + + pseudocode: select count of orders, sum of order total grouped by hour + about: given a specific hour of the day, how many orders were placed and what was the total sum of the orders? + example: e.g., "12pm has 12345 orders totaling $86753"*/ + +SELECT + EXTRACT(HOUR FROM order_date) as hour_num, --Hour extraction + COUNT(*) as order_count, --Total the number of orders + SUM(order_total_price) as total_sales --Sum the cost of the orders +FROM orders +GROUP BY + EXTRACT(HOUR FROM order_date) --Group by hour +ORDER BY + hour_num; --Go hour by hour + + + +/*Special Query 3 +Special Query #3: "Peak Sales Day" + + pseudocode: select top 10 sums of order total grouped by day in descending order by order total + about: given a specific day, what was the sum of the top 10 order totals? + example: "30 August has $12345 of top sales" +*/ +SELECT + EXTRACT(YEAR FROM order_date) as order_year, --Order year + EXTRACT(MONTH FROM order_date) as order_month, --Order month + EXTRACT(DAY FROM order_date) as order_day, --Order day + SUM(order_total_price) as total_money --Sum the sales +FROM orders +GROUP BY + order_year, order_month, order_day --Group to find individual days +ORDER BY + total_money DESC --Order by sales to get highest sales, make sure DESC to have the higest 10 first +LIMIT 10; --Limit to top 10 + + + +-- Special Query #4: "Menu Item Inventory" +-- select count of inventory items from inventory and menu grouped by menu item +-- given a specific menu item, how many items from the inventory does that menu item use? +-- DESCENDING ORDER WITH DRINKS THAT USE THE MOST ITEMS AT THE TOP +select + Drinks.Drink_ID, + Drinks.Drink_Name, + count(Drink_Recipe.Ingredient_ID) as Ingredients_Used +from Drinks +join Drink_Recipe + on Drinks.Drink_ID = Drink_Recipe.Drink_ID +group by Drinks.Drink_ID, Drinks.Drink_Name +-- order by Drinks.Drink_ID asc; +order by Ingredients_Used desc; diff --git a/SQL_Code/table_creation.sql b/SQL_Code/table_creation.sql new file mode 100644 index 0000000..ab6763e --- /dev/null +++ b/SQL_Code/table_creation.sql @@ -0,0 +1,125 @@ +create table if not exists Drink_Categories( + Drink_Category_ID int NOT NULL, + Drink_Category_NAME varchar(255) NOT NULL, + primary key (Drink_Category_ID) +); + +create table if not exists Drinks( + Drink_ID int NOT NULL, + Drink_Category_ID int NOT NULL, + Drink_Name varchar(255) NOT NULL, + Drink_Price decimal(12,2) NOT NULL, + active_months varchar(100), + primary key (Drink_ID), + foreign key(Drink_Category_ID) + references Drink_Categories(Drink_Category_ID) + ON DELETE CASCADE +); + +create table if not exists Extras_Categories ( + Extra_Category_ID int NOT NULL, + Extra_Category_NAME varchar(255) NOT NULL, + PRIMARY KEY (Extra_Category_ID) +); + +create table if not exists Extras_and_Toppings( + Extra_ID int NOT NULL, + Extra_Category_ID int NOT NULL, + Extra_Name varchar(255) NOT NULL, + Extra_Price decimal(12,2) NOT NULL, + primary key (Extra_ID), + foreign key(Extra_Category_ID) + references Extras_Categories(Extra_Category_ID) + ON DELETE CASCADE +); + +/* Unused +create table if not exists Ingredient_Categories ( + Ingredient_Category_ID int NOT NULL, + Ingredient_Category_NAME varchar(255) NOT NULL, + PRIMARY KEY (Ingredient_Category_ID) +); +*/ + +create table if not exists Inventory ( + Item_ID int NOT NULL, + Item_Name varchar(255) NOT NULL, + Item_Metric varchar(255) NOT NULL, + Item_Quantity decimal NOT NULL, + PRIMARY KEY (Item_ID) +); + +/*Unused +create table if not exists Ingredients ( + Ingredient_ID int NOT NULL, + Item_ID int NOT NULL, + Ingredient_Category_ID int NOT NULL, + Ingredient_Quantity decimal NOT NULL, + Ingredient_Metric varchar(255) NOT NULL, + PRIMARY KEY (Ingredient_ID), + FOREIGN KEY (Item_ID) + REFERENCES Inventory (Item_ID) + ON DELETE CASCADE, + FOREIGN KEY (Ingredient_Category_ID) + REFERENCES Ingredient_Categories (Ingredient_Category_ID) + ON DELETE CASCADE +); +*/ + +create table if not exists Drink_Recipe ( + Item_ID INT NOT NULL, + Drink_ID INT NOT NULL, + Quantity_Used DECIMAL NOT NULL, + FOREIGN KEY (Item_ID) + REFERENCES Inventory (Item_ID) + ON DELETE CASCADE, + FOREIGN KEY (Drink_ID) + REFERENCES Drinks (Drink_ID) + ON DELETE CASCADE +); + +create table if not exists Employees( + Employee_ID int NOT NULL, + Employee_Name varchar(100) NOT NULL, + Employee_Email varchar(100) NOT NULL, + Employee_Phone varchar(100) NOT NULL, + Employee_Position varchar(100) NOT NULL, + PRIMARY KEY (Employee_ID) +); + +create table if not exists Orders( + Order_ID int NOT NULL, + Customer varchar(100) NOT NULL, + Order_total_price decimal NOT NULL, + Order_date TIMESTAMP NOT NULL, + Employee_ID int NOT NULL, + Payment_method varchar(100) NOT NULL, + FOREIGN KEY (Employee_ID) + REFERENCES Employees (Employee_ID) + ON DELETE SET NULL, + PRIMARY KEY (Order_ID) +); + +create table if not exists Order_Items( + Order_Item_ID int NOT NULL, + Order_ID int NOT NULL, + Drink_ID int NOT NULL, + PRIMARY KEY (Order_Item_ID), + FOREIGN KEY (Order_ID) + REFERENCES Orders (Order_ID) + ON DELETE CASCADE, + FOREIGN KEY (Drink_ID) + REFERENCES Drinks (Drink_ID) + ON DELETE CASCADE +); + +create table if not exists Order_Extra( + Order_Item_ID int NOT NULL, + Extras_ID int NOT NULL, + FOREIGN KEY (Order_Item_ID) + REFERENCES Order_Items (Order_Item_ID) + ON DELETE CASCADE, + FOREIGN KEY (Extras_ID) + REFERENCES Extras_and_Toppings (Extra_ID) + ON DELETE CASCADE +);