← DoorDash Interview Insights

DoorDash·Data Scientist·Technical Phone Screen·Senior

Senior
May 2026Remote

Summary

DoorDash data science technical screen, all SQL, four questions back to back with increasingly brutal edge cases. The schema wasn't complicated but the questions had enough gotchas baked in that I was second-guessing myself the whole time.

Questions Asked (4)

Q1

Write a query to compute a 7-day rolling count of distinct active users per platform, for each calendar day in a given date range. Days with no activity for a platform should still appear with a zero count.

Product Analytics & MetricsData Modeling
Author's notes

The zero-filling part is what got me.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the schema and definitions (e.g., what constitutes an active user, platform column, date range). Then, build a query that generates a complete date-platform grid, aggregates distinct active users per day, and computes a 7-day rolling sum of distinct users using window functions, ensuring zero counts for missing days.

Pro tip: Mention that distinct counts cannot be summed directly across days; you need to either use a self-join with distinct user counting over the 7-day window or pre-aggregate at the user-day level and then count distinct users within the window. Also, highlight the importance of handling time zones and date boundaries.

1. Clarify requirements and schema

Ask about the table structure, definitions of 'active user' and 'platform', and the exact date range. Confirm whether the rolling window includes the current day and how to handle partial weeks at the start.

2. Generate a complete date-platform grid

Create a cross join between a date series covering the range and all distinct platforms to ensure every platform appears for each day, even with zero activity.

3. Aggregate daily distinct active users

Compute the number of distinct active users per platform per day from the activity table, then left join this to the date-platform grid and replace nulls with zeros.

4. Compute 7-day rolling distinct count

For each platform and day, calculate the distinct count of users active in the trailing 7-day window. This can be done via a self-join or by using a window function with a distinct count workaround (e.g., pre-aggregating user-day pairs).

5. Validate and handle edge cases

Check results for correctness, especially at the start of the range where fewer than 7 days are available. Discuss how to handle time zones and whether the rolling window should be based on calendar days or 24-hour periods.

Key Points to Mention

  • Definition of 'active user' and 'platform' (e.g., user_id, platform column, activity timestamp).
  • Use of a date dimension table or generate_series to create a complete date range.
  • Cross join with distinct platforms to ensure all platform-day combinations are present.
  • Left join and COALESCE to fill zero counts for days with no activity.
  • Window functions (e.g., ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) for rolling aggregation.
  • Challenge of distinct count in a rolling window: cannot use SUM(DISTINCT) directly; need self-join or pre-aggregation.
  • Handling of time zones and date boundaries (e.g., UTC vs local time).

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

Q2

For each product category, find the top 3 products by revenue over the last 30 days, excluding cancelled orders. Break ties by product_id ascending and output rank, revenue, category, and product_id.

Product Analytics & MetricsAlgorithms & Data Structures
Author's notes

Pretty clean once you filter the orders correctly.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and business rules (e.g., revenue definition, cancelled order status, date range). Then outline a SQL query that filters orders, aggregates revenue per product, ranks within each category using a window function, and selects the top 3 with tie-breaking by product_id. Finally, discuss validation and edge cases.

Pro tip: Mention that you would confirm whether 'revenue' means gross or net (after discounts/refunds) and whether cancelled orders are identified by a status flag or a separate table. This shows attention to data quality and business context.

1. Clarify requirements and schema

Ask about the orders table structure, how revenue is calculated, how cancelled orders are marked, and the exact date range (last 30 days from today or from a specific date).

2. Filter and aggregate

Write a subquery to filter orders within the last 30 days and exclude cancelled orders, then group by category and product_id to sum revenue.

3. Rank within categories

Use a window function like ROW_NUMBER() or RANK() with PARTITION BY category ORDER BY revenue DESC, product_id ASC to assign ranks.

4. Select top 3 and format output

Filter to ranks <= 3 and select the required columns: rank, revenue, category, product_id. Order the final result by category and rank.

5. Validate and discuss edge cases

Consider ties beyond top 3, products with zero revenue, timezone issues, and performance implications. Suggest testing with sample data.

Key Points to Mention

  • Use of window functions (ROW_NUMBER, RANK, DENSE_RANK) and the difference between them for tie-breaking.
  • Date filtering: using CURRENT_DATE - INTERVAL '30 days' or a specific date range, and handling time zones.
  • Exclusion of cancelled orders: filtering on status != 'cancelled' or joining to exclude cancelled order IDs.
  • Revenue calculation: sum of order amounts, possibly after discounts or refunds.
  • Tie-breaking logic: ORDER BY revenue DESC, product_id ASC within the window function.
  • Performance considerations: indexing on date, status, and category columns; avoiding full table scans.

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

Q3

For each user, calculate the length of their current consecutive daily login streak ending on or before a fixed reference date. A day counts if they logged in at least once.

Product Analytics & MetricsAlgorithms & Data Structures
Author's notes

I love streak questions and also kind of hate them.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the problem: define the reference date, the data schema (user_id, login_date), and confirm that a day counts if there is at least one login. Then, outline a solution that deduplicates logins per user per day, computes the difference between the reference date and each login date, and finds the longest consecutive sequence ending at the reference date. Finally, discuss how to implement this efficiently in SQL or Python, handling edge cases like missing days and users with no logins.

Pro tip: Mention that you would validate the streak calculation by manually checking a few users, and discuss how to handle time zones and the definition of a 'day' (e.g., UTC vs. local time) to avoid off-by-one errors.

1. Clarify requirements and data

Confirm the reference date, the definition of a login day (at least one login), and the expected output format. Ask about data volume and whether the solution should be in SQL or Python.

2. Preprocess data

Deduplicate logins to get one row per user per day. Ensure dates are in a consistent format and handle time zones if necessary.

3. Compute streak logic

For each user, calculate the difference in days between the reference date and each login date. Identify consecutive sequences by checking if the difference between consecutive login dates is 1 day.

4. Find current streak

Determine the streak that ends on or before the reference date. This is the length of the consecutive sequence that includes the most recent login date if it is the reference date or the day before, otherwise 0.

5. Implement and validate

Write the query or code, then test with edge cases: users with no logins, users with a gap before the reference date, and users with long streaks. Validate results manually for a few users.

Key Points to Mention

  • Deduplication of logins to ensure one record per user per day.
  • Use of window functions (e.g., ROW_NUMBER, LAG) or self-joins to identify consecutive days.
  • Handling of the reference date: streak must end on or before it, so if the last login is before the reference date minus 1, streak is 0.
  • Edge cases: users with no logins, single-day streaks, and gaps in login history.
  • Performance considerations for large datasets: indexing, partitioning, and avoiding cross joins.
  • Time zone and date boundary definitions to ensure consistency.

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

Q4

Identify users whose second non-cancelled order happened within 90 days of their signup date and whose second order's gross value was at least 1.5 times the first order's gross value. Output both order IDs, amounts, and days between them.

Product Analytics & MetricsData ModelingRoot Cause Analysis
Author's notes

This one was the most involved.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and definitions (e.g., what counts as a non-cancelled order, how to handle ties in order date). Then use a window function to rank orders per user, filter to the first two non-cancelled orders, and apply the 90-day and 1.5x value conditions. Finally, output the required fields and consider edge cases like missing signup dates or multiple orders on the same day.

Pro tip: Mention that you would validate the logic by checking a few users manually and also consider the business context: a 1.5x increase in second order value might indicate successful upselling or cross-selling, which is valuable for DoorDash. Also, be explicit about how you handle ties in order timestamps (e.g., using order ID as a tiebreaker).

1. Clarify definitions and assumptions

Confirm what 'non-cancelled' means (e.g., status not in ('cancelled', 'refunded')), how to define 'second order' (by order date or timestamp), and how to handle ties. Also clarify if signup date is always present.

2. Filter and rank orders per user

Filter out cancelled orders, then use ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date, order_id) to assign a rank to each order per user.

3. Identify first and second orders

Select users where rank = 1 (first order) and rank = 2 (second order). Join these two orders per user to compare their values and dates.

4. Apply conditions and compute metrics

Filter to cases where the second order date is within 90 days of signup date and the second order's gross value >= 1.5 * first order's gross value. Compute days between orders (second order date - first order date).

5. Output and validate

Select user_id, first_order_id, first_order_amount, second_order_id, second_order_amount, and days_between. Validate results by checking a few users manually and consider edge cases like same-day orders.

Key Points to Mention

  • Use of window functions (ROW_NUMBER) to identify the first and second non-cancelled orders per user.
  • Handling ties in order timestamps by adding a deterministic tiebreaker (e.g., order_id).
  • Definition of 'non-cancelled' orders and how to filter them.
  • Calculation of days between orders and comparison to signup date (within 90 days).
  • Comparison of gross values (second order >= 1.5 * first order).
  • Edge cases: users with only one order, missing signup dates, or orders on the same day.

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