← Meta Interview Insights

Meta·Data Scientist·Technical Phone Screen·Intermediate

Intermediate
May 2026

Summary

SQL-heavy technical screen for a Data Scientist role at Meta. Five questions all off the same orders table schema, covering filtering, aggregation, bucketing, HAVING clauses, and set operators. Pretty focused session, no behavioral stuff at all.

Questions Asked (5)

Q1

Given the orders table, return the order_id for all orders on 2025-09-01 that are paid and have an amount of at least 10. Use only a WHERE clause and list the resulting rows.

Product Analytics & MetricsTechnical Trade-offs
Author's notes

Straightforward filter question.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and data types (e.g., order_date, status, amount). Then write a single SELECT statement with a WHERE clause that filters on the date, status, and amount using appropriate operators and date formatting. Finally, execute and list the resulting order_id values.

Pro tip: Mention that you would verify the date format and timezone assumptions, and consider indexing on order_date and status for performance if the table is large.

1. Clarify schema and assumptions

Confirm column names, data types, and date format (e.g., order_date as DATE or TIMESTAMP). Check if 'paid' is a status value and if amount is numeric.

2. Construct the WHERE clause

Use conditions: order_date = '2025-09-01', status = 'paid', and amount >= 10. Combine with AND.

3. Write the full query

SELECT order_id FROM orders WHERE order_date = '2025-09-01' AND status = 'paid' AND amount >= 10;

4. Execute and list results

Run the query and list the returned order_id values. If no rows, state that clearly.

Key Points to Mention

  • Use of single quotes for string literals and date values.
  • Assumption that 'paid' is a status value; if status is stored differently (e.g., boolean), adjust accordingly.
  • Consideration of timezone if order_date includes time component.
  • Performance: indexing on order_date and status can speed up the query.
  • Edge cases: orders with amount exactly 10 are included (>=).
  • Ensure no other filters (e.g., LIMIT) are added unless specified.

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

Q2

For each user, compute their total paid amount across all dates and floor it to whole dollars. Return user_id and the floored total. Also explain why FLOOR(SUM(amount)) gives a different result than SUM(FLOOR(amount)).

Product Analytics & MetricsTechnical Trade-offs
Author's notes

The SQL part was fine.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, write a SQL query that groups by user_id, sums the amount, and applies FLOOR to the sum. Then, explain the mathematical difference between flooring after summing versus summing after flooring, using a concrete example to illustrate how rounding errors accumulate.

Pro tip: Mention that FLOOR(SUM(amount)) is the correct approach for total paid amount because it preserves the exact total before rounding, while SUM(FLOOR(amount)) can undercount due to truncating each transaction. Also, note that this distinction is crucial in financial analytics to avoid misleading metrics.

1. Understand the requirement

Clarify that the task is to compute the total paid amount per user across all dates and then floor the total to whole dollars, returning user_id and the floored total.

2. Write the SQL query

Construct a query using GROUP BY user_id, SUM(amount) to get the total, and FLOOR() to round down. Example: SELECT user_id, FLOOR(SUM(amount)) AS floored_total FROM payments GROUP BY user_id;

3. Explain the difference

Articulate that FLOOR(SUM(amount)) floors the exact total, while SUM(FLOOR(amount)) floors each transaction before summing, leading to a lower or equal result because fractional parts are discarded per transaction.

4. Provide a concrete example

Use an example like two transactions of $10.50 each: FLOOR(SUM) = FLOOR(21.00) = 21, while SUM(FLOOR) = 10 + 10 = 20, demonstrating the discrepancy.

5. Discuss implications

Highlight that the choice affects reported metrics; FLOOR(SUM) is accurate for total paid amount, whereas SUM(FLOOR) could underreport revenue and mislead stakeholders.

Key Points to Mention

  • SQL aggregation functions: SUM and FLOOR
  • Order of operations: flooring after summing vs. summing after flooring
  • Impact of rounding on financial metrics and data accuracy
  • Use of GROUP BY for per-user aggregation
  • Concrete example to illustrate the difference
  • Business implication: avoiding undercounting revenue

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

Q3

Add a value_tier column to orders using CASE WHEN: amounts under 10 are 'low', 10 to under 100 are 'mid', 100 and above are 'high'. For orders on 2025-09-01 only, return each tier and its count, ordered by tier.

Product Analytics & MetricsData Modeling
Author's notes

I made sure to be explicit about the bounds since they asked for it.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Write a single SQL query that filters orders to 2025-09-01, assigns a value tier using a CASE WHEN expression, groups by tier, and counts orders. Ensure the tier boundaries are correctly implemented (amount < 10, 10 <= amount < 100, amount >= 100) and order the results by tier. Verify that the output includes all three tiers, even if some have zero counts (though typically only non-zero tiers appear unless you use a left join with a tiers table).

Pro tip: Use a CTE or subquery to compute the tier first, then aggregate; this makes the logic clearer and avoids repeating the CASE expression. Also, explicitly handle NULL amounts if they exist, or mention that you'd exclude them based on business rules.

1. Filter orders by date

Apply a WHERE clause to select only orders from 2025-09-01. This reduces the dataset before any calculations.

2. Assign value tiers with CASE WHEN

Create a new column 'value_tier' using a CASE expression: WHEN amount < 10 THEN 'low', WHEN amount < 100 THEN 'mid', ELSE 'high'. Ensure the boundaries are correct (10 and 100 inclusive in the higher tier).

3. Group by tier and count

Use GROUP BY value_tier and COUNT(*) to get the number of orders in each tier. Alias the count column appropriately.

4. Order results by tier

Add ORDER BY value_tier to sort the output. Note that alphabetical order gives 'high', 'low', 'mid', which may not be intuitive; consider if a custom order is needed (e.g., low, mid, high) and mention it.

Key Points to Mention

  • Correct CASE WHEN syntax and boundary conditions (e.g., amount < 10, amount >= 10 AND amount < 100, amount >= 100).
  • Filtering with WHERE date = '2025-09-01' (assuming date column is named date).
  • Using GROUP BY and COUNT(*) to aggregate.
  • Ordering by tier: default alphabetical order vs. custom order (e.g., using CASE in ORDER BY).
  • Handling NULL amounts: either exclude them or assign a separate tier, depending on business rules.
  • Potential need for a CTE or subquery to avoid repeating the CASE expression and improve readability.

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

Q4

For each user, count their paid orders up to and including 2025-09-01. Return only users who have at least 2 such orders. Write the exact SQL and show the resulting rows.

Product Analytics & MetricsTechnical Trade-offs
Author's notes

Classic GROUP BY plus HAVING.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the schema and definitions of 'paid' and 'order date'. Then write a SQL query that filters orders up to the given date, groups by user, counts orders, and filters with HAVING. Finally, execute the query and present the resulting rows.

Pro tip: Always state your assumptions about the data (e.g., what 'paid' means, date format) and mention that you would validate the results with a quick sanity check, such as counting total orders before and after the date filter.

1. Clarify requirements and schema

Ask about the table structure, column names, and definitions of 'paid' and 'order date'. Confirm the date format and whether the date is inclusive.

2. Write the SQL query

Construct a query that selects user_id, counts orders, filters by date and payment status, groups by user, and uses HAVING to keep users with at least 2 orders.

3. Execute and validate

Run the query and check the results for correctness. Validate by manually inspecting a few users or comparing counts.

4. Present results

Show the resulting rows in a clear format, such as a table, and explain any assumptions made.

Key Points to Mention

  • Assumptions about the data schema and definitions (e.g., what constitutes a 'paid' order).
  • Use of WHERE clause to filter orders up to and including the specified date.
  • Use of GROUP BY and HAVING to count orders per user and filter for at least 2.
  • Consideration of date boundaries and inclusive/exclusive filtering.
  • Validation steps to ensure accuracy of results.
  • Potential need to handle NULLs or edge cases (e.g., users with no orders).

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

Q5

Using the orders table, build two subqueries: users who ordered on the web on 2025-09-01, and users who ordered in-store on the same date. Combine them with UNION and then with UNION ALL. Compare the row counts, explain which operator is more efficient and why, when you'd still use UNION despite the cost, and describe the double-counting risk when using UNION ALL to find unique users across channels.

Technical Trade-offsProduct Analytics & MetricsData Modeling
Author's notes

This was the meatiest one.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by writing the two subqueries to filter orders by channel and date, then combine them with UNION and UNION ALL to compare row counts. Explain that UNION removes duplicates (requiring a sort/hash) while UNION ALL simply concatenates, making UNION ALL more efficient. Discuss when deduplication is necessary and the double-counting risk when using UNION ALL for unique user counts.

Pro tip: Mention that if you only need unique users, using UNION ALL followed by a GROUP BY or DISTINCT can sometimes be more efficient than UNION, depending on the database optimizer. Also, highlight that UNION's deduplication can be a performance bottleneck on large datasets, so it's crucial to understand the data's cardinality.

1. Write the subqueries

Construct two SELECT statements: one for web orders on 2025-09-01 and one for in-store orders on the same date, each returning user IDs.

2. Combine with UNION and UNION ALL

Use UNION to merge the results and remove duplicates, then use UNION ALL to merge without deduplication. Compare the row counts from both operations.

3. Analyze efficiency

Explain that UNION ALL is more efficient because it avoids the costly deduplication step (sorting or hashing) that UNION performs.

4. Discuss when to use UNION

Describe scenarios where deduplication is required, such as when you need a distinct list of users across channels and cannot tolerate duplicates.

5. Explain double-counting risk

Clarify that using UNION ALL to find unique users can double-count users who ordered on both channels, leading to inflated counts.

Key Points to Mention

  • UNION removes duplicates by performing a distinct operation, which requires sorting or hashing and is resource-intensive.
  • UNION ALL simply concatenates results, preserving all rows, and is generally faster and less resource-intensive.
  • Row counts: UNION will have fewer rows if there are overlapping users; UNION ALL will have the sum of both subquery counts.
  • Use UNION when you need a deduplicated set, such as for accurate distinct user counts or when duplicates would skew metrics.
  • UNION ALL can double-count users who appear in both subqueries, so it's unsafe for unique user analysis without additional deduplication.
  • In some databases, UNION ALL followed by GROUP BY can be more efficient than UNION, especially if you need to aggregate further.

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