Mutual Channel Connections
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
Problem
Our chat platform stores one row per message, tagged with its sender and the channel it was posted to. Find the senders who have posted in both the '#engineering' and '#data-team' channels.
Two users. What channels do they share?
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
| msg_id | channel | sender_id | content | msg_type | sent_at | edited | reply_to |
|---|---|---|---|---|---|---|---|
| 147 | #engineering | 197 | Anyone seeing increased latency? | file | 2026-02-02 01:07:00 | 0 | NULL |
| 194 | #incidents | 294 | PR #412 ready for review | reaction | 2026-03-03 02:14:00 | 0 | NULL |
| 241 | #random | 391 | Dashboard is down | thread_reply | 2026-04-04 03:21:00 | 0 | NULL |
| 288 | #deployments | 488 | Fixed the flaky test | system | 2026-05-05 04:28:00 | 0 | NULL |
| 335 | #data-team | 585 | Merged the migration | Text | 2026-06-06 05:35:00 | 0 | NULL |
| 382 | #general | 682 | NULL | FILE | 2026-07-07 06:42:00 | 0 | NULL |
| 429 | #engineering | 779 | LGTM | text | 2026-08-08 07:49:00 | 0 | NULL |
| 476 | #incidents | 876 | 👍 | file | 2026-09-09 08:56:00 | 0 | 5 |
| 523 | #random | 973 | reaction | 2026-01-10 09:03:00 | 0 | NULL | |
| 570 | #deployments | 1070 | Can someone check the pipeline? | thread_reply | 2026-02-11 10:10:00 | 0 | NULL |
Expected output
| sender_id |
|---|
| 585 |
| 1167 |
| 1749 |
| 2331 |
| 2913 |
Worked solution and explanation
What this problem is really asking
Strip the chat-app framing and this is a set intersection. You need the senders who show up in the #engineering set and in the #data-team set, computed as two independent membership checks joined by AND. The word that trips people is 'both': read it as a single channel IN ('#engineering', '#data-team') filter and you have quietly asked for everyone in either channel, a union. On this data that returns 25 senders instead of 8, because plenty of people post in one of the two rooms but never the other.
Build it in two halves
Step 1: Resolve each channel's senders separately
The senders who posted in #engineering are SELECT sender_id FROM chat_msgs WHERE channel = '#engineering', and the #data-team senders are the same query with the other literal. Each is its own set; keep them apart.
Step 2: Keep only the senders in both sets
Filter chat_msgs to rows whose sender_id sits in the first set AND in the second: sender_id IN (...) AND sender_id IN (...). The AND is the intersection. Swap it for OR, or fold the two literals into one IN list, and the meaning flips to 'either channel' and the count jumps to 25.
Step 3: Collapse repeat posters to one row
Each qualifying sender has several messages in each channel, so the raw filter returns one row per message: four rows per person here. Wrap the projection in SELECT DISTINCT sender_id so the output is the set of people, not their message volume.
The solution
SELECT DISTINCT sender_id
FROM chat_msgs
WHERE sender_id IN (SELECT sender_id FROM chat_msgs WHERE channel = '#engineering')
AND sender_id IN (SELECT sender_id FROM chat_msgs WHERE channel = '#data-team')Common follow-up questions
- How would you rewrite the two `IN` subqueries as `EXISTS` clauses, and when would the planner prefer one form? (Tests whether the candidate sees each membership check as a correlated existence check and knows both forms compile to a semi-join.)
- What changes if the ask becomes senders who posted in ALL of a given list of channels, not just these two? (Pushes from a fixed two-way intersection to a general 'covers every channel' pattern, usually `GROUP BY sender_id HAVING COUNT(DISTINCT channel) = N`.)
- How would you express the same intersection with a self-join on `chat_msgs`, and why might you avoid it here? (Tests the self-join alternative and awareness that it can fan out duplicates without a careful `DISTINCT`.)