← Amazon Interview Insights

Amazon·Software Engineer·Technical Phone Screen·Intermediate

Intermediate
Jul 2026

Summary

SQL-heavy technical screen for a BI Engineer role at Amazon. Three questions, all centered on window functions and filtering logic. Nothing too wild but the second question had a wrinkle I didn't see coming.

Questions Asked (3)

Q1

Given a table of seller status events, write a query to find all seller IDs that received a 'block' or 'suspend' status at any point after a 'reinstate' status.

Data ModelingAlgorithms & Data Structures
Author's notes

Went with a self-join on the same table comparing dates.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Use a window function to compute the most recent status before each event for each seller, then filter for 'block' or 'suspend' events where the prior status was 'reinstate'. Alternatively, use a self-join to compare each event with the latest preceding event of a different status. Ensure the solution handles multiple events per seller and considers only the immediately preceding status.

Pro tip: Clarify the definition of 'after'—whether it means immediately after or any time after—and confirm if multiple blocks/suspends after a reinstate should be deduplicated. Also, mention that you'd test edge cases like sellers with no reinstate or multiple reinstates.

1. Understand the data and requirements

Identify the table schema (seller_id, status, event_time) and clarify what 'after' means (immediately or any time). Confirm if the result should be distinct seller IDs.

2. Determine the ordering of events

Use event_time to order events per seller. If ties exist, define a tie-breaker (e.g., event_id).

3. Find the previous status for each event

Use LAG() window function partitioned by seller_id and ordered by event_time to get the previous status. Alternatively, use a self-join with a subquery to find the latest event before the current one.

4. Filter for target events

Select rows where current status is 'block' or 'suspend' and previous status is 'reinstate'. Return distinct seller_id.

5. Validate and optimize

Check for edge cases (e.g., first event, multiple reinstates) and consider indexing on (seller_id, event_time) for performance.

Key Points to Mention

  • Use of window functions like LAG() to access previous row's status
  • Partitioning by seller_id and ordering by event_time
  • Handling ties in event_time with a secondary sort key
  • Filtering conditions: current status IN ('block','suspend') AND previous status = 'reinstate'
  • Returning DISTINCT seller_id to avoid duplicates
  • Performance considerations: indexing and avoiding unnecessary joins

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

Q2

For each seller, return the first status that occurs after their most recent 'reinstate' event.

Data ModelingAlgorithms & Data Structures
Author's notes

This tripped me up more than it should have.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Use a window function to rank events per seller by timestamp descending, then filter for the most recent 'reinstate' event and find the first subsequent status. Alternatively, use a correlated subquery or self-join to identify the next event after the latest reinstate per seller.

Pro tip: Clarify edge cases upfront: what if there is no 'reinstate' event for a seller, or no status after it? Discuss how to handle ties in timestamps and whether 'status' includes the reinstate event itself.

1. Understand the schema and requirements

Identify the table structure: seller_id, event_type (e.g., 'reinstate', 'status'), timestamp, and status value. Clarify that 'first status after' means the earliest event with a status type that occurs after the most recent reinstate.

2. Find the most recent reinstate per seller

Use a subquery or window function (e.g., ROW_NUMBER() OVER (PARTITION BY seller_id ORDER BY timestamp DESC)) to get the latest 'reinstate' event for each seller.

3. Identify the first status after that reinstate

For each seller, find the event with the smallest timestamp greater than the reinstate timestamp, filtering for status events. This can be done with a correlated subquery or a join with a condition on timestamp.

4. Handle edge cases and return results

Decide how to handle sellers with no reinstate or no subsequent status (e.g., exclude them or return NULL). Ensure the final query returns seller_id and the status value.

Key Points to Mention

  • Use of window functions like ROW_NUMBER() or RANK() to identify the most recent event per seller.
  • Correlated subqueries or self-joins to find the next event after a given timestamp.
  • Handling ties in timestamps: use additional ordering (e.g., event_id) or aggregate functions.
  • Edge cases: sellers without a 'reinstate' event, or with no status after the reinstate.
  • Performance considerations: indexing on (seller_id, timestamp) and avoiding full table scans.
  • Clarifying the definition of 'status'—whether it includes only specific event types or all non-reinstate events.

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

Q3

From a purchase history table, return all customer IDs that bought product 'A' at least once in 2010 and product 'B' at least once in 2018.

Product Analytics & MetricsData Modeling
Author's notes

Easier than the seller questions.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Use two separate filtered aggregations (one for product 'A' in 2010, one for product 'B' in 2018) and then find the intersection of customer IDs. This can be done with INTERSECT, INNER JOIN, or EXISTS subqueries. Ensure you handle date ranges correctly and consider performance by filtering early.

Pro tip: Mention that if the table is large, you can optimize by using EXISTS or INNER JOIN on indexed columns, and that INTERSECT may not be supported in all databases (e.g., MySQL). Also, clarify whether 'bought' means quantity > 0 or just presence of a row.

1. Clarify requirements and assumptions

Confirm the table schema (e.g., columns: customer_id, product, purchase_date, quantity) and define what 'bought' means (e.g., at least one row, or quantity > 0). Also confirm date ranges: 2010-01-01 to 2010-12-31 and 2018-01-01 to 2018-12-31.

2. Filter for product A in 2010

Write a subquery or CTE that selects distinct customer IDs where product = 'A' and purchase_date is within 2010.

3. Filter for product B in 2018

Write a similar subquery or CTE that selects distinct customer IDs where product = 'B' and purchase_date is within 2018.

4. Find the intersection

Use INTERSECT, INNER JOIN, or EXISTS to return only customer IDs that appear in both result sets. Ensure the final output is distinct customer IDs.

5. Consider performance and edge cases

Discuss indexing on (product, purchase_date) or (customer_id, product, purchase_date), and handle cases where a customer bought multiple times or in different years.

Key Points to Mention

  • Use of DISTINCT to avoid duplicate customer IDs from multiple purchases.
  • Correct date filtering: use >= '2010-01-01' AND < '2011-01-01' to avoid time component issues.
  • Choice of set operation: INTERSECT vs INNER JOIN vs EXISTS, and their availability/performance.
  • Assumption about 'bought': does it require quantity > 0 or just a row?
  • Indexing strategy for large datasets to speed up filtering.
  • Handling of NULLs or missing data in customer_id or product columns.

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