Top Active Senders per Channel

A medium SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
medium
Seniority
L4
Asked in
Meta

Problem

When several people tie for the most messages in a channel, every one of them counts as that channel's busiest sender, not just one. From chat_msgs, an analyst needs the busiest senders of each channel since July 1, with channels in alphabetical order.

Top three messages per channel by replies.

Tables

chat_msgs

Columns: msg_id INTEGER, channel TEXT, sender_id INTEGER, content TEXT, msg_type TEXT, sent_at TEXT, edited INTEGER, reply_to INTEGER

chat_msgs: 10 of 200 rows
msg_idchannelsender_idcontentmsg_typesent_ateditedreply_to
147#engineering197Anyone seeing increased latency?file2026-02-02 01:07:000NULL
194#incidents294PR #412 ready for reviewreaction2026-03-03 02:14:000NULL
241#random391Dashboard is downthread_reply2026-04-04 03:21:000NULL
288#deployments488Fixed the flaky testsystem2026-05-05 04:28:000NULL
335#data-team585Merged the migrationText2026-06-06 05:35:000NULL
382#general682NULLFILE2026-07-07 06:42:000NULL
429#engineering779LGTMtext2026-08-08 07:49:000NULL
476#incidents876👍file2026-09-09 08:56:0005
523#random973reaction2026-01-10 09:03:000NULL
570#deployments1070Can someone check the pipeline?thread_reply2026-02-11 10:10:000NULL

Expected output

First 5 of 17 rows
channelsender_idmsg_count
#data-team34952
#deployments20402
#engineering25252
#general6821
#general10701

Worked solution and explanation

What this problem really is

This is a per-group argmax with ties, dressed up as a 'busiest member' badge. Two things decide the answer, and the seed punishes getting either one wrong. First, 'busiest' is scoped to the channel. Since July 1, four channels have one sender at 2 messages, while '#general' and '#random' top out at 1, with seven and six senders tied. Compare everyone to the overall top count and those two channels vanish. Second, ties stay: keep one row per channel and 11 senders who are legitimately the busiest disappear. Drop the date filter and every channel-sender pair ties at 2, and the answer balloons to all 100 pairs.

Step 1: Count each sender's messages per channel inside the window

Filter chat_msgs to sent_at >= '2026-07-01' before GROUP BY channel, sender_id with COUNT(*). The filter changes the counts, so it has to run first. sent_at is ISO text, so the string comparison orders dates correctly. Do not filter on msg_type, edited or reply_to: every message counts.

Step 2: Place senders within each channel

DENSE_RANK() OVER (PARTITION BY channel ORDER BY msg_count DESC) gives every sender tied at the channel's top count place 1. The PARTITION BY is what makes 'top' mean this channel's top and not the workspace's.

Step 3: Keep place 1 in an outer step

A window result cannot be filtered in the WHERE of the SELECT that computes it, so the ranked CTE exists to let WHERE place = 1 run afterwards.

Step 4: Sort by channel

The list reads channel by channel, so ORDER BY channel is the whole order. Senders tied inside a channel may come in any order, and none is asked for.

The solution

Busiest senders per `channel` since the window start
WITH recent_counts AS (
    SELECT channel, sender_id, COUNT(*) AS msg_count
    FROM chat_msgs
    WHERE sent_at >= '2026-07-01'
    GROUP BY channel, sender_id
),
ranked AS (
    SELECT channel, sender_id, msg_count,
        DENSE_RANK() OVER (PARTITION BY channel ORDER BY msg_count DESC) AS place
    FROM recent_counts
)
SELECT channel, sender_id, msg_count
FROM ranked
WHERE place = 1
ORDER BY channel
Global top count
WHERE msg_count = (SELECT MAX(msg_count) FROM recent_counts) keeps the four senders at 2 messages. '#general' and '#random', whose busiest senders posted once, drop out entirely.
Per-channel top count
PARTITION BY channel resets the comparison per channel, so the seven tied senders in '#general' and the six in '#random' all come back: 17 rows.
Wrong: `ROW_NUMBER()` keeps one sender per `channel`
WITH recent_counts AS (
    SELECT channel, sender_id, COUNT(*) AS msg_count
    FROM chat_msgs
    WHERE sent_at >= '2026-07-01'
    GROUP BY channel, sender_id
),
numbered AS (
    SELECT channel, sender_id, msg_count,
        ROW_NUMBER() OVER (PARTITION BY channel ORDER BY msg_count DESC) AS rn
    FROM recent_counts
)
SELECT channel, sender_id, msg_count
FROM numbered
WHERE rn = 1
ORDER BY channel

Six rows, and which tied sender survives depends on the engine's sort.

Common follow-up questions