The Blind Spot

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
L5
Asked in
Meta

Problem

We run a content platform with a built-in team chat, and we want to recommend pages a person has not opened yet. Treat two people as connected when they have both posted in the same chat channel, and for each person surface the pages that at least two different connections have viewed but the person themselves never has.

Pages they haven't discovered yet.

Tables

page_views

Columns: view_id INTEGER, page_url TEXT, user_id INTEGER, referrer TEXT, dur_ms INTEGER, device TEXT, viewed_at TEXT

page_views: 10 of 200 rows
view_idpage_urluser_idreferrerdur_msdeviceviewed_at
5053/products1555amazon.com637desktop2026-09-02 01:09:00
5106/checkout1652twitter.com774tablet2026-09-03 02:18:00
5159/profile1749github.com911Mobile2026-09-04 03:27:00
5212/search1846NULL1048DESKTOP2026-09-05 04:36:00
5265/about1943reddit.com1185mobile2026-09-06 05:45:00
5318/blog/intro1555NULLNULLdesktop2026-09-07 06:54:00
5371/pricing1652bing.com1459tablet2026-09-08 07:03:00
5424/docs/api1749news.ycombinator.com1596Mobile2026-09-09 08:12:00
5477/settings1846NULL1733DESKTOP2026-09-10 09:21:00
5530/Home1943bing.com1870mobile2026-09-11 10:30:00

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 499 rows
user_idcontent_id
197/Home
197/checkout
197/search
197/about
197/docs/api

Worked solution and explanation

What this problem really is

This is a per-person set difference with a popularity gate, wearing a social-graph costume. The real question: take every page a person's chat connections have viewed, keep the ones at least two DIFFERENT connections saw, and subtract everything the person has already opened. Anyone can self-join chat_msgs to find who shares a channel. The hard part is proving 'two different connections' with no aggregate in the toolbox: judge popularity by counting connection-view rows and one connection who shares two channels with you, or who viewed the page five times, clears the bar alone. Then there is the exclusion: key it on user_id alone instead of the (user_id, content_id) pair and you delete pages other people viewed, not the ones this person did.


Break down the requirements

Step 1: Find each person's connections and what they viewed

connection_views self-joins chat_msgs to itself on the same channel where the two sender_id values differ, so a person is never paired with themselves, then joins to page_views on the connection's sender_id. Each row is (person, one of their connections, a page that connection viewed). Leave the rows undeduped here: the next step needs the full evidence.

Step 2: Prove two DIFFERENT connections, without counting

popular self-joins connection_views to itself on the same (user_id, content_id) where connection_id differs. A matching pair can only exist when two genuinely different connections both viewed that page for that person, so a single connection, no matter how many channels they share or how often they viewed, can never pair with themselves. SELECT DISTINCT then collapses the many surviving pairs down to one (person, page) row.

Step 3: Subtract the person's own views

LEFT JOIN popular back to page_views on BOTH user_id and page_url, then keep only the rows where the match is NULL. That NULL means this exact person never viewed this exact page, so it is a genuine recommendation.


The solution

Recommendations from connections' viewing history
WITH connection_views AS (
    SELECT cm1.sender_id AS user_id,
           cm2.sender_id AS connection_id,
           pv.page_url  AS content_id
    FROM chat_msgs cm1
    INNER JOIN chat_msgs cm2
        ON cm1.channel = cm2.channel
       AND cm1.sender_id <> cm2.sender_id
    INNER JOIN page_views pv
        ON pv.user_id = cm2.sender_id
),
popular AS (
    SELECT DISTINCT cv1.user_id, cv1.content_id
    FROM connection_views cv1
    INNER JOIN connection_views cv2
        ON cv1.user_id = cv2.user_id
       AND cv1.content_id = cv2.content_id
       AND cv1.connection_id <> cv2.connection_id
)
SELECT p.user_id, p.content_id
FROM popular p
LEFT JOIN page_views own
    ON own.user_id = p.user_id
   AND own.page_url = p.content_id
WHERE own.page_url IS NULL

Common follow-up questions