Talentd
FleetCode
Make and follow sheets.Sign in

Seasonal Sales Analysis solution and explanation

MediumDatabase7 min read64.3% acceptanceUpdated 16 Oct 2026
Leetcode MEDIUM 3564 - WINDOW FUNCTIONS in SQL - Seasonal Sales Analysis | Everyday Data ScienceEveryday Data Science · 10:58 · 1K viewsWatch on YouTube
3 more videos on this problem
  1. Leetcode MEDIUM 3564 - WINDOW FUNCTIONS in SQL - Seasonal Sales Analysis | Everyday Data ScienceEveryday Data Science · 10:58 · 1K views
  2. LeetCode 3564 – Seasonal Sales Analysis: Step-by-Step SQL Solution (Medium)InsightVanta · 13:41 · 41 views
  3. Leetcode 3564 Seasonal Sales AnalysisAlgorithmicIQ · 15:07 · 19 views
  4. LeetCode. Sql, 3564. Seasonal Sales Analysis, уровень MEDIUMДиванная аналитика · 23:08 · 4 views

The problem

Table: sales

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| sale_id       | int     |
| product_id    | int     |
| sale_date     | date    |
| quantity      | int     |
| price         | decimal |
+---------------+---------+
sale_id is the unique identifier for this table.
Each row contains information about a product sale including the product_id, date of sale, quantity sold, and price per unit.

Table: products

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| product_id    | int     |
| product_name  | varchar |
| category      | varchar |
+---------------+---------+
product_id is the unique identifier for this table.
Each row contains information about a product including its name and category.

Write a solution to find the most popular product category for each season. The seasons are defined as:

  • Winter: December, January, February
  • Spring: March, April, May
  • Summer: June, July, August
  • Fall: September, October, November

The popularity of a category is determined by the total quantity sold in that season. If there is a tie, select the category with the highest total revenue (quantity × price). If there is still a tie, return the lexicographically smaller category.

Return the result table ordered by season in ascending order.

The result format is in the following example.

Example:

Input:

sales table:

+---------+------------+------------+----------+-------+
| sale_id | product_id | sale_date  | quantity | price |
+---------+------------+------------+----------+-------+
| 1       | 1          | 2023-01-15 | 5        | 10.00 |
| 2       | 2          | 2023-01-20 | 4        | 15.00 |
| 3       | 3          | 2023-03-10 | 3        | 18.00 |
| 4       | 4          | 2023-04-05 | 1        | 20.00 |
| 5       | 1          | 2023-05-20 | 2        | 10.00 |
| 6       | 2          | 2023-06-12 | 4        | 15.00 |
| 7       | 5          | 2023-06-15 | 5        | 12.00 |
| 8       | 3          | 2023-07-24 | 2        | 18.00 |
| 9       | 4          | 2023-08-01 | 5        | 20.00 |
| 10      | 5          | 2023-09-03 | 3        | 12.00 |
| 11      | 1          | 2023-09-25 | 6        | 10.00 |
| 12      | 2          | 2023-11-10 | 4        | 15.00 |
| 13      | 3          | 2023-12-05 | 6        | 18.00 |
| 14      | 4          | 2023-12-22 | 3        | 20.00 |
| 15      | 5          | 2024-02-14 | 2        | 12.00 |
+---------+------------+------------+----------+-------+

products table:

+------------+-----------------+----------+
| product_id | product_name    | category |
+------------+-----------------+----------+
| 1          | Warm Jacket     | Apparel  |
| 2          | Designer Jeans  | Apparel  |
| 3          | Cutting Board   | Kitchen  |
| 4          | Smart Speaker   | Tech     |
| 5          | Yoga Mat        | Fitness  |
+------------+-----------------+----------+

Output:

+---------+----------+----------------+---------------+
| season  | category | total_quantity | total_revenue |
+---------+----------+----------------+---------------+
| Fall    | Apparel  | 10             | 120.00        |
| Spring  | Kitchen  | 3              | 54.00         |
| Summer  | Tech     | 5              | 100.00        |
| Winter  | Apparel  | 9              | 110.00        |
+---------+----------+----------------+---------------+

Explanation:

  • Fall (Sep, Oct, Nov):
    • Apparel: 10 items sold (6 Jackets in Sep, 4 Jeans in Nov), revenue $120.00 (6×$10.00 + 4×$15.00)
    • Fitness: 3 Yoga Mats sold in Sep, revenue $36.00
    • Most popular: Apparel with highest total quantity (10)
  • Spring (Mar, Apr, May):
    • Kitchen: 3 Cutting Boards sold in Mar, revenue $54.00
    • Tech: 1 Smart Speaker sold in Apr, revenue $20.00
    • Apparel: 2 Warm Jackets sold in May, revenue $20.00
    • Most popular: Kitchen with highest total quantity (3) and highest revenue ($54.00)
  • Summer (Jun, Jul, Aug):
    • Apparel: 4 Designer Jeans sold in Jun, revenue $60.00
    • Fitness: 5 Yoga Mats sold in Jun, revenue $60.00
    • Kitchen: 2 Cutting Boards sold in Jul, revenue $36.00
    • Tech: 5 Smart Speakers sold in Aug, revenue $100.00
    • Most popular: Tech and Fitness both have 5 items, but Tech has higher revenue ($100.00 vs $60.00)
  • Winter (Dec, Jan, Feb):
    • Apparel: 9 items sold (5 Jackets in Jan, 4 Jeans in Jan), revenue $110.00
    • Kitchen: 6 Cutting Boards sold in Dec, revenue $108.00
    • Tech: 3 Smart Speakers sold in Dec, revenue $60.00
    • Fitness: 2 Yoga Mats sold in Feb, revenue $24.00
    • Most popular: Apparel with highest total quantity (9) and highest revenue ($110.00)

The result table is ordered by season in ascending order.

Approach overview

Problem Overview: You get a sales table and a products table. Assign each sale to a season based on its month, then aggregate quantity and revenue per season and category. The result shows the leading category in each season.

Approach 1: Brute Force with Correlated Subqueries (O(S * C * N) Time, O(1) Extra Space)

For each season and category pair, run a separate subquery that scans the sales table and joins products to compute totals. The logic is easy to write because each subquery answers one question. The cost is that the sales table is scanned once per (season, category) pair. Use this only to confirm your filtering logic on small datasets.

Approach 2: Equi Join + Group Aggregation (O(N + M) Time, O(G) Space)

Join sales to products on product_id with an equality condition. Use a CASE expression on MONTH(sale_date) to map months to Winter, Spring, Summer, or Fall. Then GROUP BY season, category and apply SUM(quantity) and SUM(quantity * price). The database builds a hash table on the smaller side of the join, so each row is touched once. Here N is the number of sales rows, M is the number of products, and G is the number of season-category groups.

Approach 3: Equi Join + Group Aggregation + Window Function (O(N log N) Time, O(G) Space)

Start from Approach 2 and wrap the grouped result in a CTE. Add RANK() OVER (PARTITION BY season ORDER BY total_quantity DESC) to rank categories inside each season. Then filter to rank 1 in the outer query. The window function sorts each partition, which is where the log factor comes from. This is the cleanest way to express 'top category per season' without self-joins or repeated scans.

Recommended for interviews: Interviewers expect the join plus grouped aggregation with a window function. The brute force version shows you understand the requirement, but the window function version shows you can write set-based SQL that scales. Explain the season mapping and tie handling out loud. Mention that RANK() keeps ties while ROW_NUMBER() does not.

Related: Database, Window Functions, Joins.

Solution

Thinking

Join sales to products, map months to the four seasons, and aggregate quantity and revenue by (season,category).

Rank categories inside each season by quantity then revenue, keep rank 1, and order the rows by season. A window rank replaces a correlated subquery.

We can perform an equi join between the sales table and the products table to obtain the product category for each sales record. Next, we determine the season based on the month of the sales date, and then group by season and category to calculate the total quantity sold and total revenue. Finally, we use a window function to rank the categories within each season and select the top-ranked category.

# Write your MySQL query statement below
WITH
    SeasonalSales AS (
        SELECT
            CASE
                WHEN MONTH(sale_date) IN (12, 1, 2) THEN 'Winter'
                WHEN MONTH(sale_date) IN (3, 4, 5) THEN 'Spring'
                WHEN MONTH(sale_date) IN (6, 7, 8) THEN 'Summer'
                WHEN MONTH(sale_date) IN (9, 10, 11) THEN 'Fall'
            END AS season,
            category,
            SUM(quantity) AS total_quantity,
            SUM(quantity * price) AS total_revenue
        FROM
            sales
            JOIN products USING (product_id)
        GROUP BY 1, 2
    ),
    TopCategoryPerSeason AS (
        SELECT
            *,
            RANK() OVER (
                PARTITION BY season
                ORDER BY total_quantity DESC, total_revenue DESC, category ASC
            ) AS rk
        FROM SeasonalSales
    )
SELECT season, category, total_quantity, total_revenue
FROM TopCategoryPerSeason
WHERE rk = 1
ORDER BY 1;
import pandas as pd


def seasonal_sales_analysis(
    products: pd.DataFrame, sales: pd.DataFrame
) -> pd.DataFrame:
    df = sales.merge(products, on="product_id")
    month_to_season = {
        12: "Winter",
        1: "Winter",
        2: "Winter",
        3: "Spring",
        4: "Spring",
        5: "Spring",
        6: "Summer",
        7: "Summer",
        8: "Summer",
        9: "Fall",
        10: "Fall",
        11: "Fall",
    }
    df["season"] = df["sale_date"].dt.month.map(month_to_season)
    seasonal_sales = df.groupby(["season", "category"], as_index=False).agg(
        total_quantity=("quantity", "sum"),
        total_revenue=("quantity", lambda x: (x * df.loc[x.index, "price"]).sum()),
    )
    seasonal_sales["rk"] = (
        seasonal_sales.sort_values(
            ["season", "total_quantity", "total_revenue", "category"],
            ascending=[True, False, False, True],
        )
        .groupby("season")
        .cumcount()
        + 1
    )
    result = seasonal_sales[seasonal_sales["rk"] == 1].copy()
    return result[
        ["season", "category", "total_quantity", "total_revenue"]
    ].sort_values("season")
Try this approach in the editor

Complexity analysis

ApproachTimeSpaceWhen to Use
Correlated Subqueries (Brute Force)O(S * C * N)O(1) extraSmall data, verifying logic
Equi Join + Group AggregationO(N + M)O(G)Full season and category totals
Equi Join + Group Aggregation + Window FunctionO(N log N)O(G)Top category per season, ranking and ties

Frequently asked questions

Seasonal Sales Analysis Python solution

A Pandas solution merges the sales and products DataFrames on product_id, maps the month to a season using a dictionary or pd.cut-style logic, then groups by season and category with sum aggregations. For the top category per season, use groupby with idxmax or rank with method='min' inside each group. This mirrors the SQL join, group, and window approach.

Is Seasonal Sales Analysis easy or hard?

Seasonal Sales Analysis is a medium-difficulty problem. The hard part is not the join or the aggregation but correctly mapping months to seasons, handling ties in the ranking, and choosing the right window function. Practice writing the CTE and the RANK() filter until it feels routine.

How to solve Seasonal Sales Analysis in O(n)?

Join sales to products with a single equality condition on product_id, derive the season with a CASE expression on the month, and aggregate with GROUP BY season, category. This pass is linear in the number of rows and uses a hash-based join. The window function adds a sort step, so the full ranking output is O(N log N).

What is the best approach for Seasonal Sales Analysis?

The best approach is an equi join between sales and products, followed by grouping on season and category, and a RANK() window function to pick the top category in each season. This runs in O(N log N) time because of the window sort. It is clean, set-based SQL that works well in both MySQL and Pandas.

What data structure is used in Seasonal Sales Analysis?

The problem uses relational tables rather than a classic data structure. The database engine uses a hash table internally for the equi join and grouping step, and a sort for the window function partition. Thinking in terms of hash-based grouping and sorted partitions helps you reason about performance.

What is the time complexity of Seasonal Sales Analysis?

The optimal solution runs in O(N log N) time, where N is the number of sales rows, due to sorting inside the window function. The join and aggregation steps alone are O(N + M), where M is the number of products. The brute force version with correlated subqueries takes O(S * C * N), where S is the number of seasons and C is the number of categories.

Is Seasonal Sales Analysis asked at Google, Amazon, or Meta?

Seasonal Sales Analysis is tagged as a Database problem on FleetCode, and it is a SQL-focused question rather than a standard algorithms round. Check the company-specific tags on LeetCode for current interview reports before you plan around it. Strong SQL skills with joins, CASE, and window functions transfer to any data-heavy interview loop.

Comments

Now write it yourselfClose this page and solve Seasonal Sales Analysis in the editor, without looking.
Practise Seasonal Sales Analysis