Talentd
FleetCode
Make and follow sheets.Sign in

Market Analysis I solution and explanation

MediumDatabase6 min read58.1% acceptanceUpdated 9 Apr 2026
LeetCode Medium 1158 Interview SQL Question with Detailed ExplanationEveryday Data Science · 9:08 · 4K viewsWatch on YouTube
9 more videos on this problem
  1. LeetCode Medium 1158 Interview SQL Question with Detailed ExplanationEveryday Data Science · 9:08 · 4K views
  2. LeetCode Medium 1158 Solution with Detailed Explanation - MySQL & MS SQL ServerCode With Katia · 6:20 · 1K views
  3. 1158. Market Analysis 1 | LeetCode | SQL | Solution | Interview ProblemData Alchemist · 11:47 · 400 views
  4. Leetcode SQL | 1158.Market Analysis l #leetcodesolution #leetcodequestions #googlecloud #sqlserverMoody Mansi😉 · 6:39 · 179 views
  5. LeetCode 1158. Market Analysis I | Left join ... and | SQLSleepy Cracker · 4:15 · 157 views
  6. 1158. Market Analysis I||LeetCode - Medium||SQL #sql #insightvanta #leetcodeInsightVanta · 7:00 · 119 views
  7. Market Analysis I (Leetcode 1158) in Telugu [ASMR]Coding Interview Preparation · 7:41 · 117 views
  8. DAY 9 || 1158. Market Analysis I || SQL SERIES || LeetCode || Oracle SQLCode with Sky · 11:24 · 107 views
  9. Market Analysis I || Leetcode SQL QuestionCodeInQueries · 7:17 · 76 views
  10. LeetCode 1158 | Market Analysis I | SQL LEFT JOIN Trick Explained (ALL Buyers Count)👍🏻Vivek The Analyst · 7:01 · 35 views

The problem

Table: Users

+----------------+---------+
| Column Name    | Type    |
+----------------+---------+
| user_id        | int     |
| join_date      | date    |
| favorite_brand | varchar |
+----------------+---------+
user_id is the primary key (column with unique values) of this table.
This table has the info of the users of an online shopping website where users can sell and buy items.

Table: Orders

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| order_id      | int     |
| order_date    | date    |
| item_id       | int     |
| buyer_id      | int     |
| seller_id     | int     |
+---------------+---------+
order_id is the primary key (column with unique values) of this table.
item_id is a foreign key (reference column) to the Items table.
buyer_id and seller_id are foreign keys to the Users table.

Table: Items

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| item_id       | int     |
| item_brand    | varchar |
+---------------+---------+
item_id is the primary key (column with unique values) of this table.

Write a solution to find for each user, the join date and the number of orders they made as a buyer in 2019.

Return the result table in any order.

The result format is in the following example.

Example 1:

Input: 
Users table:
+---------+------------+----------------+
| user_id | join_date  | favorite_brand |
+---------+------------+----------------+
| 1       | 2018-01-01 | Lenovo         |
| 2       | 2018-02-09 | Samsung        |
| 3       | 2018-01-19 | LG             |
| 4       | 2018-05-21 | HP             |
+---------+------------+----------------+
Orders table:
+----------+------------+---------+----------+-----------+
| order_id | order_date | item_id | buyer_id | seller_id |
+----------+------------+---------+----------+-----------+
| 1        | 2019-08-01 | 4       | 1        | 2         |
| 2        | 2018-08-02 | 2       | 1        | 3         |
| 3        | 2019-08-03 | 3       | 2        | 3         |
| 4        | 2018-08-04 | 1       | 4        | 2         |
| 5        | 2018-08-04 | 1       | 3        | 4         |
| 6        | 2019-08-05 | 2       | 2        | 4         |
+----------+------------+---------+----------+-----------+
Items table:
+---------+------------+
| item_id | item_brand |
+---------+------------+
| 1       | Samsung    |
| 2       | Lenovo     |
| 3       | LG         |
| 4       | HP         |
+---------+------------+
Output: 
+-----------+------------+----------------+
| buyer_id  | join_date  | orders_in_2019 |
+-----------+------------+----------------+
| 1         | 2018-01-01 | 1              |
| 2         | 2018-02-09 | 2              |
| 3         | 2018-01-19 | 0              |
| 4         | 2018-05-21 | 0              |
+-----------+------------+----------------+

Approach overview

Problem Overview: You are given three tables: Users, Orders, and Items. For every user, return their user_id, join_date, and the number of orders they placed in the year 2019. Users with no orders in 2019 must still appear in the result with a count of 0. The core challenge is correctly joining user records with filtered order data while preserving users who have no matching rows.

Approach 1: SQL Join with Subquery (O(U + O) time, O(1) extra space)

This approach filters orders from 2019 first, then aggregates them per buyer before joining with the Users table. A subquery scans the Orders table, applies a YEAR(order_date) = 2019 condition, and groups results by buyer_id using COUNT(*). The outer query performs a LEFT JOIN between Users and the aggregated result so that users without orders still appear. Missing counts are replaced with 0 using COALESCE. This pattern keeps aggregation isolated and simplifies the final join, which is common in SQL interview problems involving reporting queries.

Approach 2: Iterative Filtering and Counting (O(U + O) time, O(U) space)

In languages like Java or C++, you can simulate the database logic using collections. First iterate through the orders list and filter entries where order_date belongs to 2019. Maintain a hash map that maps buyer_id → order_count, incrementing the value each time a qualifying order appears. Next iterate through the users list and construct the result by reading counts from the map, defaulting to 0 if the user never appears. This mirrors a manual hash map aggregation followed by a lookup join. The method is useful when solving database-style questions in general programming interviews or when implementing analytics logic outside a database.

Both strategies rely on the same insight: filter orders to the relevant year first, then aggregate by buyer. The SQL solution relies on relational operations like LEFT JOIN and GROUP BY, while the iterative solution uses hash-based counting and lookup logic often seen in database-style problems implemented in application code.

Recommended for interviews: The SQL aggregation with LEFT JOIN is the expected answer for database-focused interviews. It shows that you understand join semantics, grouping, and how to preserve unmatched rows. Implementing the iterative counting approach demonstrates deeper understanding of how database joins and aggregations work under the hood.

Approach 1: SQL Join with Subquery

This approach involves using SQL JOIN operations to merge relevant data from the Users and Orders tables. We focus on selecting only those orders where order_date falls in the year 2019, and then count the occurrences for each user.

import pandas as pd

users = pd.DataFrame({
    'user_id': [1, 2, 3, 4],
    'join_date': ['2018-01-01', '2018-02-09', '2018-01-19', '2018-05-21'],
    'favorite_brand': ['Lenovo', 'Samsung', 'LG', 'HP']
})

orders = pd.DataFrame({
    'order_id': [1, 2, 3, 4, 5, 6],
    'order_date': pd.to_datetime(['2019-08-01', '2018-08-02', '2019-08-03', '2018-08-04', '2018-08-04', '2019-08-05']),
    'item_id': [4, 2, 3, 1, 1, 2],
    'buyer_id': [1, 1, 2, 4, 3, 2],
    'seller_id': [2, 3, 3, 2, 4, 4]
})

# Filter orders for the year 2019
orders_2019 = orders[orders['order_date'].dt.year == 2019]

# Count orders per user
order_counts_2019 = orders_2019.groupby('buyer_id').size().reset_index(name='orders_in_2019')

# Merge with users data
total = pd.merge(users, order_counts_2019, how='left', left_on='user_id', right_on='buyer_id').fillna(0)

total['orders_in_2019'] = total['orders_in_2019'].astype(int)

# Select relevant columns
result = total[['user_id', 'join_date', 'orders_in_2019']]

print(result)
/* C solution is typically not used directly for SQL tasks but if simulating: initialize structures for Users and Orders, then proceed with filtering and counting orders per user in C code. */
SELECT u.user_id AS buyer_id, u.join_date, COUNT(o.order_id) AS orders_in_2019 FROM Users u LEFT JOIN (SELECT buyer_id, order_id FROM Orders WHERE YEAR(order_date) = 2019) o ON u.user_id = o.buyer_id GROUP BY u.user_id, u.join_date;

We use Python's pandas library to load data into DataFrames. By filtering orders to those made in 2019 and then using groupby and size to count orders per user, we mirror the SQL logic and join the resulting counts back onto the Users DataFrame to include all users.

Complexity

The time complexity is O(n + p + m), where n is the number of users, m is the number of orders, and p is the number of orders filtered for 2019. Space complexity is similarly O(n + m).

Try this approach in the editor

Approach 2: Iterative Filtering and Counting

This approach is more general-purpose and involves looping through the datasets of Users and Orders, filtering appropriate records, and calculating the desired order count for each user manually without relying on direct SQL tools.

import java.util.*;

class Solution {
    public List<Map<String, Object>> analyzeMarket(List< Map<String, Object>> users, List<Map<String, Object>> orders) {
        Map<Integer, Integer> orderCountMap = new HashMap<>();

        for (Map<String, Object> order : orders) {
            Date orderDate = (Date) order.get("order_date");
            Calendar cal = Calendar.getInstance();
            cal.setTime(orderDate);
            int year = cal.get(Calendar.YEAR);

            if (year == 2019) {
                int buyerId = (Integer) order.get("buyer_id");
                orderCountMap.put(buyerId, orderCountMap.getOrDefault(buyerId, 0) + 1);
            }
        }

        List<Map<String, Object>> result = new ArrayList<>();

        for (Map<String, Object> user : users) {
            int userId = (Integer) user.get("user_id");
            String joinDate = (String) user.get("join_date");

            Map<String, Object> entry = new HashMap<>();
            entry.put("buyer_id", userId);
            entry.put("join_date", joinDate);
            entry.put("orders_in_2019", orderCountMap.getOrDefault(userId, 0));

            result.add(entry);
        }

        return result;
    }
}
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
#include <ctime>

void analyzeMarket(const std::vector<std::tuple<int, std::string, std::string>>& users,
                   const std::vector<std::tuple<int, std::string, int, int, int>>& orders) {
    std::unordered_map<int, int> orderCountMap;

    for (const auto& order : orders) {
        std::string orderDateStr;
        int buyerId;        
        std::tie(std::ignore, orderDateStr, std::ignore, buyerId, std::ignore) = order;

        std::tm tm = {};
        std::istringstream ss(orderDateStr);
        ss >> std::get_time(&tm, "%Y-%m-%d");

        if (tm.tm_year + 1900 == 2019) {
            orderCountMap[buyerId]++;
        }
    }

    for (const auto& user : users) {
        int userId;
        std::string joinDate;
        std::tie(userId, joinDate, std::ignore) = user;

        std::cout << "buyer_id: " << userId << " join_date: " << joinDate << " orders_in_2019: " << orderCountMap[userId] << std::endl;
    }
}

This Java implementation traverses the list of orders, filtering by date to the year 2019 and populating a map with counts of orders per buyer. It then iterates over users, matching and appending their order count data.

Complexity

The time complexity is approximately O(n + m), given that we iterate through each collection separately. The process involves two main passes: one for collating the order data and another for joining this data with user data. The space complexity is O(m), where we preserve order counts in a map.

Try this approach in the editor

Complexity comparison

ApproachComplexity
SQL Join with Subquery

The time complexity is O(n + p + m), where n is the number of users, m is the number of orders, and p is the number of orders filtered for 2019. Space complexity is similarly O(n + m).

Iterative Filtering and Counting

The time complexity is approximately O(n + m), given that we iterate through each collection separately. The process involves two main passes: one for collating the order data and another for joining this data with user data. The space complexity is O(m), where we preserve order counts in a map.

Complexity analysis

ApproachTimeSpaceWhen to Use
SQL Join with SubqueryO(U + O)O(1)Best for SQL interviews and relational database queries where aggregation and joins are required
Iterative Filtering and CountingO(U + O)O(U)Useful when implementing database-style aggregation in application code using maps

Frequently asked questions

Is Market Analysis I easy or hard?

Market Analysis I is generally classified as a medium database problem. The SQL itself is straightforward once you understand LEFT JOIN behavior and GROUP BY aggregation, but many candidates miss the requirement to include users with zero orders.

Market Analysis I Python/Java solution

In Python or Java, iterate through orders and count purchases from 2019 using a hash map keyed by buyer_id. Then iterate through users and read the count from the map, defaulting to 0 when absent. This replicates SQL aggregation and join behavior with O(U + O) time complexity.

How to solve Market Analysis I in O(n)?

Filter the Orders table to include only rows where the order year is 2019, then group by buyer_id and count orders. Perform a LEFT JOIN with the Users table so every user appears in the result. The database processes both tables in linear passes, resulting in O(n) complexity relative to total rows.

What is the best approach for Market Analysis I?

The most efficient solution uses a SQL LEFT JOIN with an aggregated subquery that counts orders in 2019 for each buyer. The Orders table is filtered by year, grouped by buyer_id, and then joined with the Users table. This preserves users without orders while returning counts using COALESCE. Time complexity is O(U + O) where U is number of users and O is number of orders.

Is Market Analysis I asked at Google/Amazon/Meta?

Database aggregation and join problems similar to Market Analysis I frequently appear in interviews at companies like Amazon, Meta, and other data-heavy organizations. These questions test understanding of SQL joins, grouping, and filtering conditions rather than complex algorithms.

What data structure is used in Market Analysis I?

The SQL solution relies on relational database operations such as GROUP BY aggregation and LEFT JOIN. If implemented programmatically, a hash map (buyer_id to order count) is typically used to track counts efficiently during iteration.

What is the time complexity of Market Analysis I?

The query scans the Orders table once to filter and group orders from 2019 and scans the Users table once for the final join. This results in O(U + O) time complexity. Space overhead is minimal in SQL since aggregation is handled by the database engine.

Comments

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