0% completed
Problem Statement
Table: Orders
Each row in this table represents an individual order placed by a customer, detailing the unique order ID, customer ID, and the timestamp when the order was placed.
+---------------+------------+
| Column Name | Type |
+---------------+------------+
| order_id | int |
| customer_id | int |
| time_stamp | datetime |
+---------------+------------+
order_id is the primary key for this table.
Table: Deliveries
This table tracks the status of each order's delivery, including the order ID, the timestamp of delivery attempt, and the delivery status.
+---------------+------------+-----------------------+
| Column Name | Type | Enum |
+---------------+------------+-----------------------+
| order_id | int | |
| time_stamp | datetime | |
| status | ENUM | 'delivered', 'failed' |
+---------------+------------+-----------------------+
(order_id, time_stamp) is the primary key for this table.
order_id is a foreign key to the Orders table.
Develop a solution to calculate the fulfillment rate for each customer based on their orders. The fulfillment rate of an order is calculated as the number of 'delivered' statuses divided by the total number of delivery attempts for that order. The fulfillment rate of an order that did not have any delivery attempts is considered 0. Round the fulfillment rate to two decimal places.
Return the result table in any order.
Example
Input:
Orders table: +----------+-------------+---------------------+ | order_id | customer_id | time_stamp | +----------+-------------+---------------------+ | 1 | 100 | 2020-03-21 10:16:13 | | 2 | 200 | 2020-01-04 13:57:59 | | 3 | 100 | 2020-07-29 23:09:44 | | 4 | 300 | 2020-12-09 10:39:37 | +----------+-------------+---------------------+
Deliveries table: +----------+---------------------+-----------+ | order_id | time_stamp | status | +----------+---------------------+-----------+ | 1 | 2020-03-22 09:00:00 | delivered | | 1 | 2020-03-22 15:00:00 | failed | | 2 | 2020-01-05 14:00:00 | delivered | | 3 | 2020-08-01 00:00:00 | delivered | | 3 | 2020-08-01 12:00:00 | delivered | | 4 | 2020-12-10 11:00:00 | failed | +----------+---------------------+-----------+
Output:
+-------------+-------------------+ | customer_id | fulfillment_rate | +-------------+-------------------+ | 100 | 0.75 | | 200 | 1.00 | | 300 | 0.00 | +-------------+-------------------+
Try It Yourself
Solution
To calculate the fulfillment rate for each customer based on their orders, we need to analyze the Orders
and Deliveries
tables.
Approach Overview
-
Calculate Fulfillment Rate for Each Order:
- For each order, determine the number of
'delivered'
delivery attempts. - Calculate the total number of delivery attempts (both
'delivered'
and'failed'
). - Compute the fulfillment rate as the ratio of delivered attempts to total attempts.
- If there are no delivery attempts, assign a fulfillment rate of 0.
- For each order, determine the number of
-
Calculate Fulfillment Rate for Each Customer:
- For each customer, average the fulfillment rates of all their orders.
- Round the resulting fulfillment rate to two decimal places.
-
Present the Results:
- Display each customer's ID alongside their calculated fulfillment rate.
The provided SQL query utilizes Common Table Expressions (CTEs) to structure this solution effectively.
SQL Query
WITH OrderFulfillment AS ( -- Calculate the fulfillment rate for each order SELECT o.order_id, o.customer_id, IFNULL(SUM(CASE WHEN d.status = 'delivered' THEN 1 ELSE 0 END) / COUNT(d.order_id), 0) AS fulfillment_rate FROM Orders o LEFT JOIN Deliveries d ON o.order_id = d.order_id GROUP BY o.order_id, o.customer_id ), CustomerFulfillment AS ( -- Aggregate the fulfillment rate for each customer SELECT customer_id, ROUND(AVG(fulfillment_rate), 2) AS fulfillment_rate FROM OrderFulfillment GROUP BY customer_id ) -- Final output SELECT customer_id, fulfillment_rate FROM CustomerFulfillment;
Let's break down each part of the query step-by-step, explaining the logic and showcasing intermediate results.
Step 1: Calculate Fulfillment Rate for Each Order (OrderFulfillment
CTE)
Determine the fulfillment rate for each individual order by calculating the ratio of delivered deliveries to total delivery attempts. If an order has no delivery attempts, its fulfillment rate is set to 0.
SQL:
WITH OrderFulfillment AS ( -- Calculate the fulfillment rate for each order SELECT o.order_id, o.customer_id, IFNULL(SUM(CASE WHEN d.status = 'delivered' THEN 1 ELSE 0 END) / COUNT(d.order_id), 0) AS fulfillment_rate FROM Orders o LEFT JOIN Deliveries d ON o.order_id = d.order_id GROUP BY o.order_id, o.customer_id )
Explanation:
-
SELECT o.order_id, o.customer_id
:- Retrieves the
order_id
andcustomer_id
from theOrders
table.
- Retrieves the
-
LEFT JOIN Deliveries d ON o.order_id = d.order_id
:- Performs a left join to include all orders, even those without any corresponding deliveries. This ensures that orders with no delivery attempts are accounted for.
-
SUM(CASE WHEN d.status = 'delivered' THEN 1 ELSE 0 END)
:- Counts the number of
'delivered'
statuses for each order by summing up 1 for each'delivered'
delivery and 0 otherwise.
- Counts the number of
-
COUNT(d.order_id)
:- Counts the total number of delivery attempts for each order. This includes both
'delivered'
and'failed'
statuses.
- Counts the total number of delivery attempts for each order. This includes both
-
IFNULL(..., 0) AS fulfillment_rate
:- Calculates the fulfillment rate by dividing the number of delivered deliveries by the total delivery attempts.
- If there are no delivery attempts (
COUNT(d.order_id)
is 0), the fulfillment rate is set to 0 to avoid division by zero.
-
GROUP BY o.order_id, o.customer_id
:- Groups the results by
order_id
andcustomer_id
to perform the aggregations per order.
- Groups the results by
Intermediate Output After Step 1:
+----------+-------------+-----------------+ | order_id | customer_id | fulfillment_rate| +----------+-------------+-----------------+ | 1 | 100 | 0.50 | -- (1 delivered / 2 attempts) | 2 | 200 | 1.00 | -- (1 delivered / 1 attempt) | 3 | 100 | 1.00 | -- (2 delivered / 2 attempts) | 4 | 300 | 0.00 | -- (0 delivered / 1 attempt) +----------+-------------+-----------------+
Step 2: Aggregate Fulfillment Rate for Each Customer (CustomerFulfillment
CTE)
Compute the fulfillment rate for each customer by averaging the fulfillment rates of all their orders. The result is rounded to two decimal places for precision.
SQL:
CustomerFulfillment AS ( -- Aggregate the fulfillment rate for each customer SELECT customer_id, ROUND(AVG(fulfillment_rate), 2) AS fulfillment_rate FROM OrderFulfillment GROUP BY customer_id )
Explanation:
-
SELECT customer_id, ROUND(AVG(fulfillment_rate), 2) AS fulfillment_rate
:- For each
customer_id
, calculates the average fulfillment rate across all their orders. - The
ROUND
function ensures that the fulfillment rate is rounded to two decimal places.
- For each
-
FROM OrderFulfillment
:- Utilizes the results from the
OrderFulfillment
CTE.
- Utilizes the results from the
-
GROUP BY customer_id
:- Groups the data by
customer_id
to perform the aggregation per customer.
- Groups the data by
Intermediate Output After Step 2:
+-------------+-------------------+ | customer_id | fulfillment_rate | +-------------+-------------------+ | 100 | 0.75 | | 200 | 1.00 | | 300 | 0.00 | +-------------+-------------------+
Explanation of Intermediate Output:
-
Customer 100:
- Order 1: 0.50
- Order 3: 1.00
- Average Fulfillment Rate: (0.50 + 1.00) / 2 = 0.75
-
Customer 200:
- Order 2: 1.00
- Average Fulfillment Rate: 1.00 / 1 = 1.00
-
Customer 300:
- Order 4: 0.00
- Average Fulfillment Rate: 0.00 / 1 = 0.00
Step 3: Retrieve the Final Results
Select the customer_id
and their corresponding fulfillment_rate
from the CustomerFulfillment
CTE to present the final results.
SQL Snippet:
-- Final output SELECT customer_id, fulfillment_rate FROM CustomerFulfillment;
Explanation:
-
SELECT customer_id, fulfillment_rate
:- Retrieves each customer's ID and their calculated fulfillment rate.
-
FROM CustomerFulfillment
:- Uses the aggregated data from the
CustomerFulfillment
CTE.
- Uses the aggregated data from the
Final Output:
Based on the previous steps, the final output would be:
+-------------+-------------------+ | customer_id | fulfillment_rate | +-------------+-------------------+ | 100 | 0.75 | | 200 | 1.00 | | 300 | 0.00 | +-------------+-------------------+
.....
.....
.....
On this page
Problem Statement
Example
Try It Yourself
Solution
Approach Overview
SQL Query
Step 1: Calculate Fulfillment Rate for Each Order (OrderFulfillment
CTE)
Step 2: Aggregate Fulfillment Rate for Each Customer (CustomerFulfillment
CTE)
Step 3: Retrieve the Final Results