Correcting Order Swapping Errors in Zomato's Delivery System Using SQL
In the world of online food delivery, accuracy is paramount—whether it’s getting the right food to the right customer or ensuring that the order data is properly organized. But what happens when a technical glitch causes a mix-up in order data? This is exactly the scenario faced by Zomato, a leading food delivery platform, where due to an error in their delivery system, each food item’s order ID was swapped with the next one.
As a data analyst, your task is to identify the customers’ orders, fix this error, and return the correct order IDs and their associated items. But here’s the catch: the dataset contains a unique requirement: if the last item in the dataset has an odd order_id
, it should remain unchanged.
In this blog, we'll walk through a SQL-based solution to correct this order data by leveraging the power of window functions, specifically the ROW_NUMBER()
function. Let's dive into how we can achieve this.
Understanding the Problem
Given a table that contains orders and their corresponding food items, the order IDs have been incorrectly swapped. For instance, order_id 1
might be associated with "Chow Mein," but the system mistakenly swapped it with order_id 2
, which should have been associated with "Pizza." Our goal is to retrieve the correct pairs of order_id
and item
, ensuring the last item remains unchanged if its order_id
is odd.
Input Data:
order_id | item |
1 | Chow Mein |
2 | Pizza |
3 | Pad Thai |
4 | Butter Chicken |
5 | Eggrolls |
6 | Burger |
7 | Tandoori Chicken |
Expected Output:
corrected_order_id | item |
1 | Pizza |
2 | Chow Mein |
3 | Butter Chicken |
4 | Pad Thai |
5 | Burger |
6 | Eggrolls |
7 | Tandoori Chicken |
In the corrected output, you’ll notice that:
The odd-numbered order IDs are paired correctly with the next even-numbered rows.
The last row (with
order_id 7
) remains unchanged since it has an oddorder_id
.
The Solution
We can solve this problem using a combination of SQL features, particularly window functions. Let’s break down the solution step by step.
Step 1: Using ROW_NUMBER()
to Track Row Positions
The first task is to assign a unique sequential number to each row. This will help us track the position of each row and determine whether it’s an odd or even-numbered row.
We can achieve this using the ROW_NUMBER()
window function, which assigns an integer to each row, ordered by the order_id
.
WITH NumberedOrders AS (
SELECT
order_id,
item,
ROW_NUMBER() OVER (ORDER BY order_id) AS rn
FROM orders
)
Here:
ROW_NUMBER() OVER (ORDER BY order_id)
generates a sequential row number (rn
) for each row in the table, ordered by theorder_id
.The result is a temporary table (
NumberedOrders
) with theorder_id
,item
, and a new columnrn
that tracks the row’s position.
Step 2: Swap Logic Using CASE
Now that we have a row number for each record, we can use the CASE
statement to swap the rows. The logic is simple:
For odd-numbered rows (
rn % 2 = 1
), swap with the next row (rn + 1
).For even-numbered rows (
rn % 2 = 0
), swap with the previous row (rn - 1
).For the last row, if it has an odd
order_id
, leave it as is.
Here’s the SQL query implementing this logic:
SELECT
CASE
-- For odd rows, swap with the next row
WHEN rn % 2 = 1 AND rn + 1 <= (SELECT COUNT(*) FROM orders) THEN
(SELECT order_id FROM NumberedOrders WHERE rn = o.rn + 1)
-- For even rows, swap with the previous row
WHEN rn % 2 = 0 THEN
(SELECT order_id FROM NumberedOrders WHERE rn = o.rn - 1)
-- For the last row with an odd order_id, leave it unchanged
ELSE
o.order_id
END AS corrected_order_id,
CASE
-- For odd rows, swap with the next row
WHEN rn % 2 = 1 AND rn + 1 <= (SELECT COUNT(*) FROM orders) THEN
(SELECT item FROM NumberedOrders WHERE rn = o.rn + 1)
-- For even rows, swap with the previous row
WHEN rn % 2 = 0 THEN
(SELECT item FROM NumberedOrders WHERE rn = o.rn - 1)
-- For the last row with an odd order_id, leave it unchanged
ELSE
o.item
END AS item
FROM NumberedOrders o;
Explanation of the Query:
NumberedOrders
CTE:- We first generate a temporary table with
order_id
,item
, and a sequentialrn
(row number) usingROW_NUMBER()
.
- We first generate a temporary table with
CASE
Statement:For odd
rn
, we fetch the values of the next row (rn + 1
), which "fixes" the swap.For even
rn
, we fetch the values of the previous row (rn - 1
).The
ELSE
clause ensures that the last row (if it has an oddorder_id
) stays unchanged.
Final Output:
After running this query, we will get the corrected order IDs and items, with the data displayed in the correct pairing order, as shown below:
corrected_order_id | item |
1 | Pizza |
2 | Chow Mein |
3 | Butter Chicken |
4 | Pad Thai |
5 | Burger |
6 | Eggrolls |
7 | Tandoori Chicken |
Conclusion
By using SQL’s ROW_NUMBER()
function in combination with CASE
statements, we can easily fix a situation where rows have been incorrectly swapped, without modifying the underlying data in the database. This approach ensures:
No data modification: We simply adjust how the data is retrieved, not how it’s stored.
Efficient and dynamic swapping: The
ROW_NUMBER()
function allows us to track row positions and swap rows based on their sequential order.Handles edge cases: The logic ensures that the last row, if it has an odd
order_id
, remains unchanged.
With this method, Zomato's data can be quickly and accurately corrected, restoring the integrity of the order information without any manual intervention or database updates. This is a great example of how SQL can be used to solve real-world data issues in a dynamic and efficient manner.
I hope you found this article helpful in understanding how to solve such data issues with SQL! Stay tuned for more insights on how to use SQL to solve common data problems.
Happy Querying 🔥🚀