← OPPO Interview Insights

OPPO·Software Engineer·Technical Phone Screen·Intermediate

Intermediate
Jul 2026

Summary

SQL-heavy technical screen for a Data Engineer role at OPPO. Three questions, each harder than the last, and by the third one I was definitely sweating. The jump from basic aggregation to gaps-and-islands with membership windows was pretty steep.

Questions Asked (3)

Q1

Given an Orders table with order_id, customer_id, amount, and order_date, write a query that returns each customer's total spend and number of orders for the full year 2024, sorted by total spend descending.

Data ModelingAlgorithms & Data Structures
Author's notes

Warmup question, pretty much.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and the requirement to filter orders to the full year 2024. Then write a SQL query that groups by customer_id, computes SUM(amount) and COUNT(order_id), and orders the results by total spend descending. Explain each clause and consider edge cases like date boundaries and customers with no orders.

Pro tip: Mention that using COUNT(*) is fine for counting orders, but if order_id can be NULL, COUNT(order_id) is safer; also highlight that filtering with order_date >= '2024-01-01' AND order_date < '2025-01-01' avoids timezone and inclusivity issues.

1. Clarify requirements and schema

Confirm the table structure, data types, and that 'full year 2024' means orders from Jan 1 to Dec 31, 2024. Ask if customers with zero orders should be included.

2. Filter for 2024 orders

Use a WHERE clause to restrict to orders in 2024, preferably with a half-open interval to handle timestamps correctly.

3. Aggregate per customer

Group by customer_id and compute SUM(amount) as total_spend and COUNT(order_id) as order_count.

4. Sort and present results

Order the results by total_spend descending, and optionally include customer_id in the output.

5. Discuss edge cases and optimizations

Mention handling of NULLs, customers with no orders, and potential indexing on order_date or customer_id for performance.

Key Points to Mention

  • Use of GROUP BY customer_id with aggregate functions SUM and COUNT.
  • Filtering with order_date >= '2024-01-01' AND order_date < '2025-01-01' to include the full year and avoid boundary issues.
  • Ordering by total_spend DESC to meet the sorting requirement.
  • Handling of NULL values in amount or order_id (e.g., COUNT(order_id) vs COUNT(*)).
  • Consideration of customers with zero orders (e.g., using LEFT JOIN from a customers table if needed).
  • Potential performance improvements via indexing on order_date and customer_id.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Given a Transactions table with user_id, amount, and created_at, compute a 7-day rolling sum of amount for each user across every calendar date in the dataset, including dates where the user had no transactions.

Data ModelingAlgorithms & Data StructuresProduct Analytics & Metrics
Author's notes

This is where things got uncomfortable.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, generate a complete date-user grid by cross joining distinct users with a date series covering the dataset's range. Then left join transactions to this grid, aggregate daily sums (coalescing nulls to 0), and compute the 7-day rolling sum using a window function partitioned by user and ordered by date with a ROWS BETWEEN 6 PRECEDING AND CURRENT ROW frame.

Pro tip: Clarify whether the rolling window should include only days with transactions or all calendar days; the latter requires the date spine. Also, mention that using a window frame of 6 preceding rows assumes one row per date per user, which the grid ensures.

1. Generate a complete date-user grid

Create a date series covering the min to max created_at, then cross join with distinct user_ids to get every user-date combination.

2. Aggregate daily transaction amounts

Group the original transactions by user_id and date to get daily sums, then left join to the grid and replace nulls with 0.

3. Compute 7-day rolling sum

Use a window function: SUM(amount) OVER (PARTITION BY user_id ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW).

4. Handle edge cases and validate

Ensure dates with no transactions show 0, and verify that the rolling sum correctly includes the current day and the previous 6 days.

Key Points to Mention

  • Date spine generation using GENERATE_SERIES or a calendar table
  • Cross join to create all user-date combinations
  • Left join and COALESCE to fill missing transaction days with 0
  • Window function with PARTITION BY user_id and ORDER BY date
  • ROWS BETWEEN 6 PRECEDING AND CURRENT ROW for 7-day window
  • Performance considerations: indexing on user_id and created_at, and filtering date range

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

Given a Sessions table and a Memberships table, find users who had any session activity during periods when their membership was inactive, and return each user's total minutes of session time that fell outside their active membership window.

Data ModelingAlgorithms & Data StructuresSystem Design
Author's notes

Hardest of the three by a mile.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the schema and definitions of 'inactive' and 'session activity'. Then, use a join between Sessions and Memberships on user_id, filter for sessions that fall outside any active membership period, and sum the overlapping minutes per user.

Pro tip: Watch for overlapping membership periods and sessions that span active/inactive boundaries; compute the intersection of session intervals with inactive periods to avoid double-counting.

1. Clarify requirements and schema

Ask about the table structures, how active membership is defined (e.g., start_date, end_date), and whether sessions can span multiple days or overlap with multiple memberships.

2. Identify inactive periods

For each user, determine the time intervals when they had no active membership. This may involve finding gaps between membership periods or using a calendar table.

3. Compute session time outside active membership

For each session, calculate the portion of its duration that falls within inactive periods. Sum these durations per user.

4. Handle edge cases and validate

Consider overlapping memberships, sessions that start before and end after an active period, and users with no memberships. Validate with sample data.

5. Write and optimize the query

Use SQL with interval logic (e.g., generate_series, window functions, or self-joins) to compute the total inactive session minutes per user. Discuss indexing and performance.

Key Points to Mention

  • Definition of 'inactive': no active membership covering the session time.
  • Interval overlap calculation: session_start < membership_end AND session_end > membership_start.
  • Handling multiple memberships and overlapping periods.
  • Using a calendar or date dimension table to simplify gap analysis.
  • Performance considerations: indexing on user_id and date columns.
  • Edge cases: sessions with zero duration, users with no sessions, memberships with NULL end dates.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.