Most Popular Active Plan for the Top Event Type
Reported by candidates from Notion's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
The mistake that sinks a first attempt on this Notion OA question is picking the top event type after joining to subscriptions. Notion, reported March 2026, wants the top event type by raw event rows first, then the plan with the most matching events during that type. It's a SQL question with a CTE, a range join, and two alphabetical tiebreaks. If the query goes blank on you mid-assessment, StealthCoder runs invisibly as a safety net while you work through the join.
The problem
First find the event type with the most event rows. Break an event-type tie alphabetically. For events of that type, join the subscription active at each event time and return the plan with the most matching events. A subscription is active when start_time <= event_time < end_time; a null end_time means it is still active. Break a plan tie alphabetically. Return plan_type and event_count. Tables events: event_id PK (Integer), user_id (Integer), event_type (Text), event_time (Timestamp) subscriptions: subscription_id PK (Integer), user_id (Integer), plan_type (Text), start_time (Timestamp), end_time (Timestamp) Constraints At most one subscription is active for a user at any event time. The selected top event type has at least one event with an active subscription. The end boundary is exclusive.
Reported by candidates. Source: FastPrep
Pattern and pitfall
The trick is order of operations. Step one: group events by event_type, order by count descending then event_type ascending, limit 1. That count must come from the events table alone, not from a join, because users without a subscription still count. Step two: join the filtered events to subscriptions on user_id with event_time >= start_time AND (end_time IS NULL OR event_time < end_time). The end boundary is exclusive, so using <= is the classic pitfall. Then group by plan_type, count events, order by event_count descending then plan_type ascending, limit 1. Since at most one subscription is active per user at any time, the join won't double count. Don't use an inner join before picking the top type. A CTE for the top type keeps it readable. If you freeze on the NULL end_time handling, StealthCoder is the hedge during the live OA.
If this hits your live OA and you blank, StealthCoder solves it in seconds, invisible to the proctor.
You can drill Most Popular Active Plan for the Top Event Type cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built by an Amazon engineer who would have shipped this the night before his JPMorgan OA if he'd had it.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Notion's OA.
Notion reuses patterns across OAs. Built by an Amazon engineer who would have shipped this the night before his JPMorgan OA if he'd had it. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Most Popular Active Plan for the Top Event Type FAQ
What's the trick in this Notion SQL question?+
Pick the top event type from the events table alone, before any join. Users with no subscription still count toward the event-type total. Then range-join subscriptions on the filtered events and count by plan_type. Doing it in two CTEs keeps each step clean.
How do I handle the null end_time?+
Treat null as still active. Write the join condition as event_time >= start_time AND (end_time IS NULL OR event_time < end_time). You can also use COALESCE with a far-future date. Either way, keep the end boundary exclusive with a strict less-than.
How do I break ties correctly?+
Use ORDER BY with the count descending first, then the name ascending. Do it twice: event_type for the top type, then plan_type for the final plan. Then add LIMIT 1 each time. Skipping the secondary sort is the quickest way to fail a hidden test.
Can the join double count events?+
Not here. The constraints say at most one subscription is active for a user at any event time, so each event matches at most one row. Overlapping ranges would break that, but the problem rules them out. Counting event_id is still a safe habit.
How do I prepare for this in 48 hours?+
Practice range joins with half-open intervals, NULL handling in join conditions, and CTEs that chain a top-1 result into a second query. Write the query out twice from scratch. Focus on tiebreak ordering and boundary operators, since those cause most wrong answers.