Watch 2 video solutions for Year on Year Growth Rate, a hard level problem involving Database. This walkthrough by ItJunction4all has 1,722 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Table: user_transactions
+------------------+----------+ | Column Name | Type | +------------------+----------+ | transaction_id | integer | | product_id | integer | | spend | decimal | | transaction_date | datetime | +------------------+----------+ The transaction_id column uniquely identifies each row in this table. Each row of this table contains the transaction ID, product ID, the spend amount, and the transaction date.
Write a solution to calculate the year-on-year growth rate for the total spend for each product.
The result table should include the following columns:
year: The year of the transaction.product_id: The ID of the product.curr_year_spend: The total spend for the current year.prev_year_spend: The total spend for the previous year.yoy_rate: The year-on-year growth rate percentage, rounded to 2 decimal places.Return the result table ordered by product_id,year in ascending order.
The result format is in the following example.
Example:
Input:
user_transactions table:
+----------------+------------+---------+---------------------+ | transaction_id | product_id | spend | transaction_date | +----------------+------------+---------+---------------------+ | 1341 | 123424 | 1500.60 | 2019-12-31 12:00:00 | | 1423 | 123424 | 1000.20 | 2020-12-31 12:00:00 | | 1623 | 123424 | 1246.44 | 2021-12-31 12:00:00 | | 1322 | 123424 | 2145.32 | 2022-12-31 12:00:00 | +----------------+------------+---------+---------------------+
Output:
+------+------------+----------------+----------------+----------+ | year | product_id | curr_year_spend| prev_year_spend| yoy_rate | +------+------------+----------------+----------------+----------+ | 2019 | 123424 | 1500.60 | NULL | NULL | | 2020 | 123424 | 1000.20 | 1500.60 | -33.35 | | 2021 | 123424 | 1246.44 | 1000.20 | 24.62 | | 2022 | 123424 | 2145.32 | 1246.44 | 72.12 | +------+------------+----------------+----------------+----------+
Explanation:
Note: Output table is ordered by product_id and year in ascending order.
Problem Overview: The task is to compute the year‑on‑year (YoY) growth rate of a metric stored in a database table. For each year (and typically for each entity such as product or company), you aggregate the metric, find the value from the previous year, and calculate the percentage change using (current - previous) / previous.
Approach 1: Grouping Statistics + Left Join (O(n log n) time, O(n) space)
Start by aggregating the metric by year using GROUP BY. This produces one row per year with the total value you want to analyze. Next, self‑join this aggregated dataset with itself using a LEFT JOIN where the current year matches the previous year plus one. The join exposes both the current year's total and the previous year's total in the same row, allowing you to compute the YoY growth rate using a simple arithmetic expression.
This approach relies on standard SQL operations: grouping, joining, and arithmetic expressions. The key insight is that YoY growth is simply a comparison between adjacent years, so joining the dataset with a shifted version of itself solves the alignment problem. A LEFT JOIN ensures that the earliest year still appears even when no previous year exists. Aggregation and sorting during grouping typically lead to O(n log n) processing time in most SQL engines, with O(n) intermediate storage for the grouped results.
This method is widely supported across relational systems and works cleanly in MySQL where window functions may not always be the preferred option. It fits naturally with concepts from SQL, database querying, and relational joins.
Approach 2: Window Function with LAG (O(n log n) time, O(n) space)
An alternative solution uses a window function such as LAG(). After computing yearly aggregates, apply LAG(total_value) ordered by year to access the previous year's value in the same result set. The growth rate can then be calculated directly without a self‑join.
The advantage of this method is readability. Window functions make sequential comparisons explicit and eliminate the need for manual join conditions. Internally, the database still sorts rows by year, so the complexity remains roughly O(n log n) with O(n) memory for the window frame.
Recommended for interviews: The grouping + left join approach is the safest answer. It shows you understand relational joins and how to align records across time periods. Mentioning the window function alternative demonstrates deeper SQL knowledge and awareness of modern query features.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Grouping Statistics + Left Join | O(n log n) | O(n) | Most portable SQL solution; works across MySQL and common relational databases |
| Window Function (LAG) | O(n log n) | O(n) | Cleaner query when window functions are supported and dataset is already grouped by year |