A Data-Driven Pizza Parlor

GOAL

RESULT

PROJECT DURATION

Adrian’s Pizzeria aims to enhance its pizza-making and optimize business operations through data-driven decision-making.

A comprehensive report with insights and recommendations for Adrian’s Pizzeria, facilitating well-informed decisions, cost savings, and process optimization.

The estimated duration of the project is 2 to 3 months, depending on the availability, completeness, and cleanliness of the data.

CASE – OPTIMIZING ADRIAN'S PIZZERIA OPERATIONS

In the bustling world of pizzerias, there’s a hidden gem called “Slice of Poznań.” What sets Adrian’s apart isn’t just its mouthwatering pizzas but its dedication to data-driven decision-making.

The owner Adrian is on a mission to perfect his pizza-making game and optimize his business operations. Let’s dive into how Adrian’s Pizzeria uses data to make every slice count.

Orders: The Heart of the Business

At Slice of Poznań, every order tells a story, and Adrian wants to capture that narrative through data. Here’s what he needs:

  • Item name: To know what pizzas are popular.
  • Item price: To analyze pricing strategies.
  • Quantity: To track demand.
  • Customer name: For personalization.
  • Delivery address: To ensure popular locations
  • Row ID: A unique identifier for orders.
  • Order ID: A unique code for each customer’s order.
  • Item Name: The name of the ordered pizza.
  • Item Category: The pizza’s group, like “Vegetarian.”
  • Item Size: The pizza size (e.g., small, medium).
  • Item Price: The cost of the pizza.
  • Quantity: The number of pizzas ordered.
  • Customer First Name: Customer’s first name.
  • Customer Last Name: Customer’s last name.
  • Delivery Address: The address for pizza delivery.
  • Delivery City: The city for delivery.
  • Delivery Zip Code: The zip code for delivery location.

Stock Control: Keeping the Pantry Full

Adrian doesn’t want to run out of ingredients during the dinner rush. To prevent this, he needs:

  • Ingredients list for each pizza: To know what goes into each pizza.
  • Quantity of ingredients per pizza size: Plan inventory based on size.

Imagine making sure you have enough pepperoni and cheese for every pizza size; that level of accuracy is exactly what we’re aiming for.

Staff Control: Making Sure the Team Is Set

Adrian knows that his skilled chefs and delivery staff are key to his success. To manage his team effectively, he wants to:

  • Know which staff members are working and when: For efficient staffing.

By understanding labor costs, Adrian can make data-driven decisions on staffing and pricing.

Table Creation

Let’s begin by creating the necessary tables for MySQL usage.

CREATE TABLE `orders` (
`row_id` int NOT NULL ,
`order_id` varchar(10) NOT NULL ,
`created_at` datetime NOT NULL ,
`item_id` varchar(10) NOT NULL ,
`quantity` int NOT NULL ,
`cust_id` int NOT NULL ,
`delivery` boolean NOT NULL ,
`add_id` int NOT NULL ,
PRIMARY KEY (
`row_id`
)
);
CREATE TABLE `customers` (
`cust_id` int NOT NULL ,
`cust_firstname` varchar(50) NOT NULL ,
`cust_lastname` varchar(50) NOT NULL ,
PRIMARY KEY (
`cust_id`
)
);

CREATE TABLE `address` (
`add_id` int NOT NULL ,
`delivery_address1` varchar(200) NOT NULL ,
`delivery_city` varchar(50) NOT NULL ,
`delivery_zipcode` varchar(20) NOT NULL ,
PRIMARY KEY (
`add_id`
)
);

CREATE TABLE `item` (
`item_id` varchar(10) NOT NULL ,
`sku` varchar(20) NOT NULL ,
`item_name` varchar(100) NOT NULL ,
`item_cat` varchar(100) NOT NULL ,
`item_size` varchar(10) NOT NULL ,
`item_price` decimal(10,2) NOT NULL ,
PRIMARY KEY (
`item_id`
)
);

CREATE TABLE `ingredient` (
`ing_id` varchar(10) NOT NULL ,
`ing_name` varchar(200) NOT NULL ,
`ing_weight` int NOT NULL ,
`ing_meas` varchar(20) NOT NULL ,
`ing_price` decimal(5,2) NOT NULL ,
PRIMARY KEY (
`ing_id`
)
);

CREATE TABLE `recipe` (
`row_id` int NOT NULL ,
`recipe_id` varchar(20) NOT NULL ,
`ing_id` varchar(10) NOT NULL ,
`quantity` int NOT NULL ,
PRIMARY KEY (
`row_id`
)
);

CREATE TABLE `inventory` (
`inv_id` int NOT NULL ,
`item_id` varchar(10) NOT NULL ,
`quantity` int NOT NULL ,
PRIMARY KEY (
`inv_id`
)
);

CREATE TABLE `staff` (
`staff_id` varchar(20) NOT NULL ,
`first_name` varchar(50) NOT NULL ,
`last_name` varchar(50) NOT NULL ,
`position` varchar(100) NOT NULL ,
`hourly_rate` decimal(5,2) NOT NULL ,
PRIMARY KEY (
`staff_id`
)
);

CREATE TABLE `shift` (
`shift_id` varchar(20) NOT NULL ,
`day_of_week` varchar(10) NOT NULL ,
`start_time` time NOT NULL ,
`end_time` time NOT NULL ,
PRIMARY KEY (
`shift_id`
)
);

CREATE TABLE `rota` (
`row_id` int NOT NULL ,
`rota_id` varchar(20) NOT NULL ,
`date` datetime NOT NULL ,
`shift_id` varchar(20) NOT NULL ,
`staff_id` varchar(20) NOT NULL ,
PRIMARY KEY (
`row_id`
)
);

How tables look after they are created at QuickDatabaseDiagrams.com

Dashboards: Visualizing the Journey with Tableau

Now, let’s talk about the dashboards Adrian uses to make sense of all this data:

Dashboard 1: Order Activity

This dashboard provides a bird’s-eye view of Adrian’s Pizzeria:

  • Total orders: Tracking overall demand.
  • Total sales: Measuring revenue.
  • Total items: Understanding inventory usage.
  • Average order value: Analyzing spending habits.
  • Sales by category: Identifying popular pizza types.
  • Top selling items: Knowing customer favorites.
  • Orders by hour: Optimizing staffing.
  • Sales by hour: Identifying peak sales times.
  • Orders by address: Targeting delivery areas.

Adrian uses this dashboard to fine-tune his operations, from staffing to inventory management.

The SQL code I used to create the first dashboard, which we’ll call “Dashboard 1 — Orders.” This query retrieves data from various tables and joins them to provide insights into order activity. Here’s an explanation of the code:

SELECT
o.order_id,
i.item_price,
o.quantity,
i.item_cat,
i.item_name,
o.created_at,
a.delivery_address1,
a.delivery_city,
a.delivery_zipcode,
o.delivery
FROM
orders o
LEFT JOIN item i ON o.item_id = i.item_id
LEFT JOIN address a ON o.add_id = o.add_id
  • SELECT: Specifies the columns you want to include in the result set.
  • o.order_id: Retrieves the unique order ID.
  • i.item_price: Fetches the item price (pizza price).
  • o.quantity: Gets the quantity of items (number of pizzas) in the order.
  • i.item_cat: Retrieves the item category (e.g., “Vegetarian”).
  • i.item_name: Fetches the item name (pizza name).
  • o.created_at: Retrieves the order creation timestamp.
  • a.delivery_address1: Fetches the delivery address.
  • a.delivery_city: Retrieves the delivery city.
  • a.delivery_zipcode: Retrieves the delivery zip code.
  • o.delivery: Retrieves delivery-related data (possibly a status or method).

This query combines data from the “orders,” “item,” and “address” tables using LEFT JOINs based on the appropriate keys (e.g., order_id, item_id, add_id). It collects essential information about each order, including details about the pizzas, delivery, and customer addresses.

Dashboard 2: Inventory Management

This dashboard provides detailed information on the ingredients used and their respective costs.Total quantity by ingredient: Monitoring ingredient usage.

  • Total cost of ingredients: Tracking expenses.
  • Calculated cost of each pizza: Ingredient costs + labor costs.

By utilizing this data, Adrian can secure a constant supply of vital ingredients and make informed decisions about pizza pricing to maximize profits.


SQL Code for Inventory Analysis:

SELECT
    s1.item_name,
    s1.ing_id,
    s1.ing_name,
    s1.ing_weight,
    s1.ing_price,
    s1.order_quantity,
    s1.recipe_quantity,
    s1.order_quantity * s1.recipe_quantity AS ordered_weight,
    s1.ing_price / s1.ing_weight AS unit_cost,
    (s1.order_quantity * s1.recipe_quantity) * (s1.ing_price / s1.ing_weight) AS ingredient_cost
FROM
    (
        SELECT
            o.item_id,
            i.sku,
            i.item_name,
            r.ing_id,
            r.quantity AS recipe_quantity,
            SUM(o.quantity) AS order_quantity,
            ing.ing_weight,
            ing.ing_price,
            ing.ing_name
        FROM
            orders o
        LEFT JOIN
            item i ON o.item_id = i.item_id
        LEFT JOIN
            recipe r ON i.sku = r.recipe_id
        LEFT JOIN
            ingredient ing ON ing.ing_id = r.ing_id 
        GROUP BY
            o.item_id,
            i.sku,
            i.item_name,
            r.ing_id,
            r.quantity,
            ing.ing_name,
            ing.ing_weight,
            ing.ing_price
    ) s1;

Creating the Inventory View:

We begin by creating a view called “stock1” to work with the data more effectively:

CREATE VIEW stock1 AS
SELECT
    s1.item_name,
    s1.ing_id,
    s1.ing_name,
    s1.ing_weight,
    s1.ing_price,
    s1.order_quantity,
    s1.recipe_quantity,
    s1.order_quantity * s1.recipe_quantity AS ordered_weight,
    s1.ing_price / s1.ing_weight AS unit_cost,
    (s1.order_quantity * s1.recipe_quantity) * (s1.ing_price / s1.ing_weight) AS ingredient_cost
FROM
    (
        SELECT
            o.item_id,
            i.sku,
            i.item_name,
            r.ing_id,
            r.quantity AS recipe_quantity,
            SUM(o.quantity) AS order_quantity,
            ing.ing_weight,
            ing.ing_price,
            ing.ing_name
        FROM
            orders o
        LEFT JOIN
            item i ON o.item_id = i.item_id
        LEFT JOIN
            recipe r ON i.sku = r.recipe_id
        LEFT JOIN
            ingredient ing ON ing.ing_id = r.ing_id 
        GROUP BY
            o.item_id,
            i.sku,
            i.item_name,
            r.ing_id,
            r.quantity,
            ing.ing_name,
            ing.ing_weight,
            ing.ing_price
    ) s1;

Analyzing Remaining Ingredients:

Lastly, we calculate the total weight of inventory for each ingredient and determine how much is left in stock:

SELECT
    s2.ing_name,
    s2.ordered_weight,
    ing.ing_weight * inv.quantity as total_inv_weight,
    (ing.ing_weight * inv.quantity) - s2.ordered_weight as remaining_weight
FROM (SELECT 
    ing_id,
    ing_name,
    SUM(ordered_weight) as ordered_weight
    FROM 
    stock1
    GROUP BY ing_name, ing_id) s2
LEFT JOIN inventory inv ON inv.item_id = s2.ing_id
LEFT JOIN ingredient ing ON ing.ing_id = s2.ing_id;

This analysis allows Adrian’s Pizzeria to make informed decisions about restocking, ingredient costs, pricing, and profitability of each pizza.

Dashboard 3 — Staff Management: Tracking the Workforce


In this segment of Adrian’s Pizzeria’s data journey, we concentrate on managing the staff workforce, utilizing data from three critical tables: rota, staff, and shift.

SQL Code for Staff Analysis:

Step 1: Joining Rota and Staff Tables

We start by joining the “rota” and “staff” tables to create a comprehensive view of staff scheduling:

SELECT
    r.date,
    s.first_name,
    s.last_name,
    s.hourly_rate
FROM
    rota r
LEFT JOIN
    staff s ON r.staff_id = s.staff_id;

Step 2: Including Shift Information

Next, we add shift data to the mix, creating a more detailed picture of staff schedules:

SELECT
    r.date,
    s.first_name,
    s.last_name,
    s.hourly_rate,
    sh.start_time,
    sh.end_time
FROM
    rota r
LEFT JOIN
    staff s ON r.staff_id = s.staff_id
LEFT JOIN
    shift sh ON r.shift_id = sh.shift_id;

Step 3: Calculating Staff Costs

Lastly, we calculate the cost of staffing by determining the hours worked and multiplying them by the hourly rate using the TIMEDIFF() function:

SELECT
    r.date,
    s.first_name,
    s.last_name,
    s.hourly_rate,
    sh.start_time,
    sh.end_time,
    (
        (HOUR(TIMEDIFF(sh.end_time, sh.start_time)) * 60) + MINUTE(TIMEDIFF(sh.end_time, sh.start_time))
    ) / 60 AS hours_in_shift,
    (
        (
            HOUR(TIMEDIFF(sh.end_time, sh.start_time)) * 60
        ) + MINUTE(TIMEDIFF(sh.end_time, sh.start_time))
    ) / 60 * s.hourly_rate AS staff_cost
FROM
    rota r
LEFT JOIN
    staff s ON r.staff_id = s.staff_id
LEFT JOIN
    shift sh ON r.shift_id = sh.shift_id;

This data analysis helps Adrian’s Pizzeria efficiently manage its staff schedules and calculate the associated costs, ensuring a well-organized and cost-effective workforce.

You can access my imaginary datasets on my Github and Kaggle accounts for your use and modification.

GitHub
hberksafak's Blue Github Chart
Tableau
Kaggle
Copyright © | 2023 by Hasan Berk Şafak
Scroll to Top