← Meta Interview Insights

Meta·Data Scientist·Technical Phone Screen·Senior

Senior
Jun 2026

Summary

SQL-heavy Data Scientist screen at Meta, four back-to-back analytical questions all built around the same schema. The whole thing felt like a take-home but live, which was stressful. Lots of edge cases baked in intentionally.

Questions Asked (4)

Q1

Given a schema with Users, Posts, PostHashtags, and Impressions tables, write a query to find the top hashtags by unique viewers over the last 7 days. Return the hashtag, unique viewer count, and rank, breaking ties deterministically. Use date functions instead of hardcoded dates.

Product Analytics & MetricsData Modeling
Author's notes

This one was more about window functions than anything else.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by identifying the necessary joins: Impressions to Posts to PostHashtags to get hashtags for each impression, then filter impressions to the last 7 days using a date function like CURRENT_DATE - INTERVAL '7 days'. Count distinct users per hashtag, rank them using a window function with deterministic tie-breaking (e.g., by count descending, then hashtag ascending), and return the top results.

Pro tip: Clarify whether 'unique viewers' means distinct users who saw any post with that hashtag, and ensure you handle ties deterministically by adding a secondary sort key like hashtag name. Also, consider if impressions can have multiple hashtags per post and whether that affects distinct counts.

1. Understand the schema and metric

Identify the relevant tables and columns: Users (user_id), Posts (post_id, user_id), PostHashtags (post_id, hashtag), Impressions (impression_id, post_id, viewer_id, timestamp). Clarify that 'unique viewers' means distinct viewer_id per hashtag.

2. Filter impressions to last 7 days

Use a date function to dynamically filter impressions, e.g., WHERE timestamp >= CURRENT_DATE - INTERVAL '7 days'. Avoid hardcoded dates.

3. Join tables to associate hashtags with impressions

Join Impressions to Posts on post_id, then to PostHashtags on post_id to get hashtag for each impression. Ensure you keep viewer_id for distinct counting.

4. Aggregate unique viewers per hashtag

Group by hashtag and count distinct viewer_id to get unique viewer count. Use COUNT(DISTINCT viewer_id).

5. Rank hashtags deterministically

Use a window function like RANK() or DENSE_RANK() OVER (ORDER BY unique_viewers DESC, hashtag ASC) to assign ranks. The secondary sort on hashtag ensures deterministic tie-breaking.

Key Points to Mention

  • Use of COUNT(DISTINCT viewer_id) to calculate unique viewers.
  • Dynamic date filtering with CURRENT_DATE - INTERVAL '7 days' instead of hardcoded dates.
  • Proper join path: Impressions -> Posts -> PostHashtags to link viewers to hashtags.
  • Window function (RANK or DENSE_RANK) with ORDER BY unique_viewers DESC, hashtag ASC for deterministic ranking.
  • Consideration of potential duplicates: a viewer may see multiple posts with the same hashtag, so distinct count is necessary.
  • Awareness of time zone or timestamp granularity if relevant (e.g., using DATE(timestamp) for daily boundaries).

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

Q2

For each hashtag in the last 7 days, compute the click-through rate defined as distinct users who clicked the hashtag divided by distinct users who were exposed to it. Make sure the denominator only counts exposures where that specific hashtag was present on the post, and avoid double-counting users who saw the same hashtag across multiple posts.

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

CTR queries sound simple but this one had a real trap around the denominator.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the definitions of exposure and click events, then outline a SQL-based approach that joins exposure and click tables on hashtag and user, using COUNT(DISTINCT user_id) for both numerator and denominator. Emphasize the need to filter exposures to only those posts containing the specific hashtag and to deduplicate users per hashtag before computing the ratio.

Pro tip: Mention that you would validate the metric by checking for edge cases like users who clicked without exposure or hashtags with zero exposures, and consider segmenting by user demographics or hashtag popularity to uncover actionable insights.

1. Clarify definitions and assumptions

Confirm what constitutes an exposure (e.g., post impression) and a click (e.g., hashtag click), and ensure the time window is exactly the last 7 days. Ask if there are any bot filters or minimum exposure thresholds to apply.

2. Identify relevant tables and fields

Locate the exposure table (with post_id, user_id, timestamp, and hashtags array) and the click table (with user_id, hashtag, timestamp). Ensure both tables have the necessary join keys and time filters.

3. Compute distinct exposed users per hashtag

For each hashtag, explode the hashtags array in the exposure table, filter to the last 7 days, and count distinct user_ids. This gives the denominator, ensuring each user is counted once per hashtag even if exposed multiple times.

4. Compute distinct clicking users per hashtag

From the click table, filter to the last 7 days, group by hashtag, and count distinct user_ids. This gives the numerator. Optionally, join with exposures to ensure clicks are attributed only to users who were exposed to that hashtag.

5. Calculate CTR and handle edge cases

Join the numerator and denominator by hashtag, compute CTR as clicks/exposures, and handle hashtags with zero exposures (e.g., exclude or set CTR to 0). Validate results by checking for anomalies and consider adding filters for statistical significance.

Key Points to Mention

  • Use COUNT(DISTINCT user_id) for both numerator and denominator to avoid double-counting users.
  • Ensure the denominator only includes exposures where the specific hashtag was present on the post (e.g., by exploding the hashtags array).
  • Filter both exposures and clicks to the last 7 days using timestamp fields.
  • Consider joining clicks with exposures to ensure clicks are only counted for users who were exposed to that hashtag (if required).
  • Handle edge cases such as hashtags with zero exposures or users who clicked without exposure.
  • Validate the metric by checking for data quality issues (e.g., bot traffic, duplicate events) and consider segmenting by hashtag popularity or user demographics.

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

Q3

For each post created in the last 7 days, recommend up to 2 hashtags that its viewers clicked most in the last 30 days, excluding hashtags already on the post. Use a LEFT JOIN with IS NULL to handle the exclusion. Then explain exactly what rows would be lost if you swapped that LEFT JOIN for an INNER JOIN, paying special attention to posts with no hashtags at all and posts whose viewers never clicked anything.

Data ModelingTechnical Trade-offsProduct Analytics & Metrics
Author's notes

This was the hardest one.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, outline the SQL query structure: a CTE or subquery to aggregate click counts per post and hashtag over the last 30 days, then join to posts from the last 7 days using LEFT JOIN with IS NULL to exclude existing hashtags, and rank to pick top 2. Then, explain the semantic difference between LEFT JOIN and INNER JOIN, focusing on which rows are dropped and why that matters for posts with no hashtags or no clicks.

Pro tip: Emphasize that the LEFT JOIN with IS NULL is not just a filter but a deliberate choice to preserve posts that have zero eligible hashtags, ensuring they appear in the output with NULL recommendations—this is crucial for product completeness and avoids silently dropping content.

1. Clarify the data model and requirements

Identify the tables involved (posts, hashtag_clicks, post_hashtags) and confirm the time windows: posts from last 7 days, clicks from last 30 days. Define 'viewers clicked most' as the hashtags with the highest click counts by viewers of that post.

2. Construct the aggregation and join logic

Write a subquery to count clicks per post per hashtag in the last 30 days. Then LEFT JOIN this to the posts from the last 7 days, and use a second LEFT JOIN to the post's existing hashtags with a WHERE clause that filters out matches (IS NULL) to exclude already-used hashtags.

3. Rank and limit to top 2 hashtags per post

Use a window function like ROW_NUMBER() OVER (PARTITION BY post_id ORDER BY click_count DESC) to rank hashtags per post, then filter to rank <= 2. Ensure posts with no eligible hashtags still appear with NULLs.

4. Analyze the impact of swapping LEFT JOIN for INNER JOIN

Explain that INNER JOIN would drop any post that has no matching rows in the joined table. Specifically, posts with no hashtags at all (no rows in post_hashtags) and posts whose viewers never clicked any hashtag (no rows in the click aggregation) would be lost entirely from the result set.

5. Discuss product implications and trade-offs

Highlight that using INNER JOIN would silently exclude posts that might still be relevant for recommendation (e.g., new posts with no clicks yet), leading to incomplete recommendations and potential bias against new or low-engagement content. LEFT JOIN ensures all posts are considered, even if no hashtags are recommended.

Key Points to Mention

  • LEFT JOIN with IS NULL is used to exclude hashtags already on the post by filtering out matches, while preserving posts that have no existing hashtags.
  • INNER JOIN would drop posts with no hashtags at all because there would be no matching rows in the post_hashtags table.
  • INNER JOIN would also drop posts whose viewers never clicked any hashtag in the last 30 days, as there would be no rows in the click aggregation to join.
  • The difference matters for product completeness: posts with no recommendations should still appear (with NULLs) to avoid missing content in downstream systems.
  • Time windows are critical: posts from last 7 days, clicks from last 30 days—ensure the join conditions respect these windows.
  • Ranking with window functions (e.g., ROW_NUMBER) is necessary to limit to top 2 hashtags per post without losing posts that have fewer than 2 eligible hashtags.

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

Q4

Write a query to find posts that have zero hashtags but received more than one impression in the last 7 days. Explain why a RIGHT JOIN is unnecessary here and how a LEFT JOIN from Posts to PostHashtags lets you detect posts with no matching child rows.

Data ModelingTechnical Trade-offs
Author's notes

Easiest of the four.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and the definition of 'impression' (e.g., a row in an Impressions table). Then write a query that LEFT JOINs Posts to PostHashtags, filters for NULL hashtag IDs to find posts with zero hashtags, and joins to an impressions table to count impressions in the last 7 days, using HAVING to filter for more than one impression. Finally, explain why a RIGHT JOIN is unnecessary: a LEFT JOIN from Posts to PostHashtags already preserves all posts, and the NULL check identifies those without hashtags.

Pro tip: Mention that using NOT EXISTS or a subquery with NOT IN can be an alternative to LEFT JOIN for finding posts with no hashtags, but LEFT JOIN with IS NULL is often more efficient and easier to read, especially when combined with other joins. Also, clarify the grain of the impressions data to avoid double-counting.

1. Clarify schema and requirements

Ask about the tables involved (Posts, PostHashtags, Impressions) and confirm the definition of 'impression' and 'last 7 days' (e.g., based on current date or a specific timestamp).

2. Identify posts with zero hashtags

Use a LEFT JOIN from Posts to PostHashtags and filter WHERE PostHashtags.PostID IS NULL to get posts that have no matching hashtag rows.

3. Filter by impressions in last 7 days

Join the result to an Impressions table (or equivalent) on PostID, filter for impressions within the last 7 days, and group by post to count impressions.

4. Apply HAVING clause for >1 impression

Use HAVING COUNT(*) > 1 (or SUM(impression_count) > 1) to keep only posts with more than one impression.

5. Explain why RIGHT JOIN is unnecessary

Explain that a LEFT JOIN from Posts to PostHashtags already includes all posts, and the NULL check identifies those without hashtags. A RIGHT JOIN would return all PostHashtags rows, which is not needed because we want posts, not hashtags.

Key Points to Mention

  • LEFT JOIN preserves all rows from the left table (Posts) and matches rows from the right table (PostHashtags); unmatched rows get NULLs.
  • Checking for NULL in the right table's primary key (e.g., PostHashtags.PostID IS NULL) identifies posts with no hashtags.
  • A RIGHT JOIN would return all PostHashtags rows, which is the opposite of what we want; it would not help find posts with zero hashtags.
  • Aggregation with GROUP BY and HAVING is needed to count impressions per post and filter for >1.
  • Date filtering should be applied to the impressions timestamp to consider only the last 7 days.
  • Consider performance: indexing on PostHashtags.PostID and Impressions.PostID and timestamp can speed up the query.

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