← Uber Interview Insights

Uber·Data Scientist·Technical Phone Screen·Senior

Senior
Sep 2025Remote

Summary

Uber DS interview, technical phone screen or take-home style, all SQL and Pandas. Five questions across ride-share analytics scenarios. Pretty brutal if you're rusty on window functions.

Questions Asked (5)

Q1

Given a trips table with request_time, city, and status, compute per-city total requests, completed trips, and completion rate for the last 7 days. Order results by completion rate ascending.

Product Analytics & MetricsData Modeling
Author's notes

Seemed straightforward but I kept second-guessing whether to filter on request_time or dropoff_time.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and definitions: what statuses indicate a completed trip, how to handle time zones, and whether 'last 7 days' means a rolling window or calendar days. Then write a SQL query that filters trips to the last 7 days, groups by city, and computes total requests, completed trips, and completion rate. Finally, order by completion rate ascending and discuss edge cases like cities with zero requests.

Pro tip: Mention that completion rate should be calculated as completed trips divided by total requests, and consider using NULLIF to avoid division by zero. Also, highlight the importance of aligning the time window with the business definition (e.g., last 7 full days vs. last 168 hours).

1. Clarify requirements and definitions

Ask clarifying questions about the status values (e.g., 'completed', 'cancelled'), the definition of 'last 7 days' (rolling vs. calendar), and time zone handling. Confirm that completion rate is completed/total requests.

2. Filter and aggregate data

Write a SQL query that filters trips where request_time is within the last 7 days, groups by city, and calculates total requests (COUNT(*)), completed trips (SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END)), and completion rate.

3. Handle edge cases and ordering

Use NULLIF or a CASE statement to avoid division by zero. Order the results by completion rate ascending. Consider whether to include cities with zero requests (likely exclude).

4. Validate and interpret results

Sanity-check the output: ensure completion rates are between 0 and 1, and consider if any cities have unusually low or high rates. Discuss potential data quality issues (e.g., missing statuses).

Key Points to Mention

  • Definition of 'completed' status and how to handle other statuses (e.g., cancelled, in-progress).
  • Time window: rolling 7 days vs. calendar days, and time zone considerations.
  • SQL aggregation techniques: COUNT, SUM with CASE, and GROUP BY city.
  • Completion rate calculation: completed / total, with NULLIF to prevent division by zero.
  • Ordering by completion rate ascending and filtering out cities with no requests.
  • Potential data quality issues: missing or inconsistent status values, duplicate records.

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

Q2

For each driver over the last 7 days, compute the ratio of average surge multiplier during the 20:00-21:59 window versus 14:00-15:59 on completed trips, bucketed by city and day. Return only drivers where both windows have at least one trip and the ratio exceeds 1.5.

Product Analytics & MetricsData ModelingRoot Cause Analysis
Author's notes

This one took me a minute.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the data model and metric definitions, then outline a SQL query that filters completed trips in the last 7 days, computes average surge per driver per city per day for each time window, and joins the results to calculate the ratio. Finally, apply the conditions: both windows must have at least one trip and the ratio must exceed 1.5.

Pro tip: Mention that you would validate the surge multiplier field for outliers or missing values and consider whether the ratio should be weighted by trip volume or simply the ratio of averages, as this can significantly impact results.

1. Clarify requirements and data model

Confirm definitions: completed trips, surge multiplier, time windows, and the 7-day period. Identify relevant tables (e.g., trips, drivers, cities) and ensure you understand how surge is recorded.

2. Filter and aggregate trips by window

Write a subquery to select completed trips from the last 7 days, extract the date and hour, and classify each trip into the 20:00-21:59 or 14:00-15:59 window. Compute average surge per driver, city, and day for each window.

3. Join and compute ratio

Join the two aggregated results on driver, city, and day, ensuring both windows have at least one trip. Calculate the ratio of the evening average surge to the afternoon average surge.

4. Apply final filter and output

Filter to only rows where the ratio exceeds 1.5 and return the driver, city, day, and ratio. Consider ordering or limiting results as needed.

Key Points to Mention

  • Use of conditional aggregation (CASE WHEN) to compute averages for each time window in a single pass.
  • Ensuring both windows have at least one trip by using INNER JOIN or HAVING COUNT > 0.
  • Handling time zones and date boundaries correctly, especially for the 'last 7 days' definition.
  • Considering whether to weight surge by trip volume or use simple average, and discussing the implications.
  • Validating data quality: checking for null surge values, outliers, and ensuring trips are completed.
  • Optimizing the query for performance, e.g., using appropriate indexes or partitioning by date.

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

Q3

Compute the median pickup wait time per city for completed trips over the last 7 days, but first exclude any trips above the city-specific 95th percentile wait. Use window functions for both the percentile cutoff and the median.

Product Analytics & MetricsAlgorithms & Data Structures
Author's notes

Percentile_cont inside a window frame is one of those things I always have to look up.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and definitions (completed trips, wait time, city, date range). Then use a window function to compute the 95th percentile wait per city, filter out trips above that cutoff, and finally compute the median wait per city using another window function (e.g., PERCENTILE_CONT or NTILE).

Pro tip: Mention that percentile functions like PERCENTILE_CONT are analytic functions and can be used in a subquery or CTE to avoid self-joins, and that you'd validate the 95th percentile cutoff doesn't disproportionately remove data from small cities.

1. Clarify requirements and data model

Confirm definitions: completed trips, pickup wait time, city, and last 7 days. Identify the relevant table and columns (e.g., trips with status, timestamps, city_id).

2. Compute city-specific 95th percentile wait

Use a window function like PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY wait_time) OVER (PARTITION BY city) to calculate the cutoff per city.

3. Filter out trips above the cutoff

In a CTE or subquery, exclude trips where wait_time > city_95th_percentile. Ensure the filter is applied before median calculation.

4. Compute median wait per city

Use another window function (e.g., PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY wait_time) OVER (PARTITION BY city)) on the filtered dataset to get the median.

5. Present final result and discuss edge cases

Select distinct city and median wait. Discuss handling of ties, small sample sizes, and whether to round or report percentiles.

Key Points to Mention

  • Use of PERCENTILE_CONT or PERCENTILE_DISC for percentile and median calculations
  • PARTITION BY city to compute per-city metrics
  • Filtering with a subquery or CTE to apply the 95th percentile cutoff before median
  • Ensuring only completed trips and last 7 days are included
  • Handling of NULL wait times and cities with insufficient data
  • Performance considerations: window functions can be expensive, so filter early if possible

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

Q4

Identify likely duplicate rider accounts by finding rider pairs who share either the same device ID or the same payment card hash on trips taken in the last 30 days. Return the pair with a < b ordering, the evidence type, evidence value, and first seen time.

Data ModelingRoot Cause AnalysisProduct Analytics & Metrics
Author's notes

Favorite question of the set.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and defining the time window (last 30 days). Then, for each evidence type (device ID and payment card hash), self-join the trips table on the evidence column to find rider pairs, ensuring rider_id1 < rider_id2 to avoid duplicates. Finally, union the results, deduplicate, and select the required columns including the earliest trip timestamp as first_seen.

Pro tip: Mention that you would handle potential NULLs in device_id or payment_card_hash by filtering them out before joining, and consider using a window function to get the first seen time efficiently. Also, discuss how to scale the query for large datasets, e.g., using partitioning or sampling if needed.

1. Clarify requirements and data schema

Confirm the table structure, column names, and definitions (e.g., rider_id, device_id, payment_card_hash, trip_date). Ensure the time window is correctly interpreted as the last 30 days from the current date.

2. Filter trips to last 30 days

Apply a WHERE clause to restrict the trips to those taken in the last 30 days, reducing the dataset size for subsequent joins.

3. Self-join on device_id and payment_card_hash

Perform two separate self-joins: one on device_id and one on payment_card_hash, ensuring rider_id1 < rider_id2 to avoid duplicate pairs and self-pairs. Extract the evidence type and value from the join key.

4. Union and deduplicate results

Combine the results from both joins using UNION ALL, then deduplicate pairs that may appear multiple times (e.g., same pair sharing both device and card). For each pair and evidence type, compute the earliest trip timestamp as first_seen.

5. Format and validate output

Select the final columns: rider_a, rider_b, evidence_type, evidence_value, first_seen. Validate that the output meets the requirements (e.g., no duplicate pairs, correct ordering).

Key Points to Mention

  • Use of self-join to find pairs sharing the same device ID or payment card hash.
  • Ensuring rider_id1 < rider_id2 to avoid duplicate pairs and maintain consistent ordering.
  • Handling NULL values in device_id or payment_card_hash by excluding them from joins.
  • Computing first_seen as the minimum trip timestamp for each pair and evidence type.
  • Deduplicating pairs that may share both device and card, or appear multiple times.
  • Considering scalability and performance for large datasets (e.g., indexing, partitioning).

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

Q5

Using Pandas, compute 7-day new-user retention by cohort for riders whose first completed trip falls within a given date range. A rider is retained if they have at least one additional completed trip within 7 days of their first. Return cohort_date, number of new riders, retained count, and retention rate.

Product Analytics & MetricsA/B Testing & Experimentation
Author's notes

Pandas after four SQL questions felt like a gear shift.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, filter trips to completed ones and compute each rider's first trip date. Then, for each rider, check if they have another completed trip within 7 days of their first trip, and aggregate by cohort date (first trip date) to calculate new riders, retained count, and retention rate.

Pro tip: Clarify the definition of 'within 7 days'—whether it's inclusive or exclusive—and confirm that retention is based on any trip after the first, not necessarily the second trip. Also, consider timezone and date boundaries.

1. Filter and prepare data

Filter the trips DataFrame to only completed trips and ensure the date column is in datetime format. Optionally, filter to the given date range for first trips.

2. Identify first trips

For each rider, find the minimum trip date (first completed trip). This defines the cohort date for each rider.

3. Determine retention

For each rider, check if there exists another completed trip within 7 days after their first trip date. Create a boolean flag for retention.

4. Aggregate by cohort

Group by cohort_date (first trip date) and compute the number of new riders (count of riders) and retained count (sum of retention flag). Calculate retention rate as retained count divided by new riders.

5. Format output

Return a DataFrame with columns: cohort_date, new_riders, retained_count, retention_rate. Ensure the date range filter is applied to cohort_date if specified.

Key Points to Mention

  • Definition of retention: at least one additional completed trip within 7 days of first trip.
  • Handling of date ranges: filter first trips to the given date range.
  • Use of groupby and aggregation functions in Pandas.
  • Efficiency considerations: merging or using transform to avoid loops.
  • Edge cases: riders with only one trip, trips exactly on the 7th day, timezone handling.
  • Clear output format: cohort_date, new_riders, retained_count, retention_rate.

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