Cross-Platform Engagement Correlation
For each active user, count posts, comments, likes, sent messages, and stories; classify their primary engagement type; and rank their weighted total activity.
- Window functions
- Joins
- Subqueries
- Aggregation
- CASE expressions
Challenge brief
Understand the request
Product Analytics needs a reliable cross-surface engagement profile to understand which interaction type is most prominent for each active user.
Fan-out-safe engagement breakdown with primary activity classification and a weighted rank.
Return
- username
- posts_count
- comments_count
- likes_count
- messages_count
- stories_count
- primary_engagement_type
- activity_rank (RANK by weighted total)
Constraints
- Return active users only
- Weighted activity = posts*5 + comments*3 + likes*1 + sent messages*2 + stories*4
- Count each surface independently before combining it with the user population
- When activity counts tie, classify by this priority: Content Creator, Commenter, Liker, Messenger, Story Viewer
Data you will use
Review the relevant tables before deciding how to join, filter, or aggregate them.
users
user_idINTEGERusernameVARCHAR(50)statusVARCHAR(20)
posts
post_idINTEGERuser_idINTEGER
comments
comment_idINTEGERuser_idINTEGER
likes
like_idINTEGERuser_idINTEGER
messages
message_idINTEGERsender_idINTEGER
stories
story_idINTEGERuser_idINTEGER
Hints, when you need them
Open one clue at a time so you still do the reasoning.
Hint 1
Two CTEs. CTE 1 user_activity: LEFT JOIN users to each of 5 tables (posts, comments, likes, messages on sender_id, stories), COUNT(DISTINCT ...) each, WHERE active. CTE 2 engagement_type: CASE WHEN logic for primary type and weighted score.
Hint 2
Five LEFT JOINs from users. COUNT(DISTINCT ...) for each surface. CASE WHEN: whichever count leads = that type. Weighted = posts*5 + comments*3 + likes*1 + messages*2 + stories*4.
Hint 3
Start with the tables that establish the result grain for question 15, select the required output aliases, and add the remaining joins, filters, aggregation, and ordering one clause at a time.
Verified SQL answer
Attempt the problem first, then compare structure and reasoning—not just syntax.
Reveal solution and explanation
WITH post_counts AS (SELECT user_id, COUNT(*) AS posts_count FROM posts GROUP BY user_id), comment_counts AS (SELECT user_id, COUNT(*) AS comments_count FROM comments GROUP BY user_id), like_counts AS (SELECT user_id, COUNT(*) AS likes_count FROM likes GROUP BY user_id), message_counts AS (SELECT sender_id AS user_id, COUNT(*) AS messages_count FROM messages GROUP BY sender_id), story_counts AS (SELECT user_id, COUNT(*) AS stories_count FROM stories GROUP BY user_id), user_activity AS (SELECT u.user_id, u.username, COALESCE(p.posts_count, 0) AS posts_count, COALESCE(c.comments_count, 0) AS comments_count, COALESCE(l.likes_count, 0) AS likes_count, COALESCE(m.messages_count, 0) AS messages_count, COALESCE(s.stories_count, 0) AS stories_count FROM users u LEFT JOIN post_counts p ON u.user_id = p.user_id LEFT JOIN comment_counts c ON u.user_id = c.user_id LEFT JOIN like_counts l ON u.user_id = l.user_id LEFT JOIN message_counts m ON u.user_id = m.user_id LEFT JOIN story_counts s ON u.user_id = s.user_id WHERE u.status = 'active'), engagement_type AS (SELECT user_id, username, posts_count, comments_count, likes_count, messages_count, stories_count, CASE WHEN posts_count >= comments_count AND posts_count >= likes_count AND posts_count >= messages_count AND posts_count >= stories_count THEN 'Content Creator' WHEN comments_count >= likes_count AND comments_count >= messages_count AND comments_count >= stories_count THEN 'Commenter' WHEN likes_count >= messages_count AND likes_count >= stories_count THEN 'Liker' WHEN messages_count >= stories_count THEN 'Messenger' ELSE 'Story Viewer' END AS primary_engagement_type, posts_count * 5 + comments_count * 3 + likes_count + messages_count * 2 + stories_count * 4 AS total_activity_score FROM user_activity) SELECT username, posts_count, comments_count, likes_count, messages_count, stories_count, primary_engagement_type, RANK() OVER (ORDER BY total_activity_score DESC) AS activity_rank FROM engagement_type ORDER BY activity_rank, username;Why this works
Aggregate each one-to-many activity surface independently before joining it to users. This avoids a large Cartesian fan-out and makes every count correct by construction.
Success check
4 active users with fan-out-safe surface counts; john_doe ranks first after both of his stories are counted.
Expected result
Use this output to verify values, aliases, ordering, and row count.
| username | posts_count | comments_count | likes_count | messages_count | stories_count | primary_engagement_type | activity_rank |
|---|---|---|---|---|---|---|---|
| john_doe | 2 | 1 | 1 | 1 | 2 | Content Creator | 1 |
| jane_smith | 2 | 1 | 2 | 1 | 1 | Content Creator | 2 |
| sarah_jones | 1 | 1 | 1 | 0 | 1 | Content Creator | 3 |
| mike_wilson | 1 | 1 | 1 | 1 | 0 | Content Creator | 4 |
Learn the concepts behind this answer
Strengthen your understanding with these targeted learning topics:
Continue practicing
Explore related company challenges
Google
Independent Google-style search, advertising, user-engagement, and video-product SQL practice.
Netflix
Independent Netflix-style streaming, subscription, catalog, ratings, and engagement SQL practice.
Airbnb
Independent Airbnb-style marketplace, booking, listing, payment, review, and guest analytics SQL practice.
Return to the complete interview preparation experience.