Searches by Users With Email

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

Domain
SQL
Difficulty
easy
Seniority
L3
Asked in
ESPN

Problem

The search quality team is analyzing result effectiveness but only for identifiable users. Pull all search query details for users who have an email address on file, limited to queries that returned at least one result.

One user's search behavior.

Tables

search_queries

Columns: query_id INTEGER, user_id INTEGER, search_term TEXT, results_count INTEGER, clicked_result INTEGER, query_time TEXT

search_queries: 10 of 200 rows
query_iduser_idsearch_termresults_countclicked_resultquery_time
2071100laptop deals1722026-02-02 01:11:00
2142197phone case iphone 153432026-03-03 02:22:00
2213294usb-c cable 6ft51NULL2026-04-04 03:33:00
2284NULLgaming mouse6852026-05-05 04:44:00
2355488mechanical keyboard8562026-06-06 05:55:00
24265854k monitor102NULL2026-07-07 06:06:00
2497682standing desk11982026-08-08 07:17:00
2568NULLwebcam 1080p13692026-09-09 08:28:00
2639876bluetooth speaker153NULL2026-01-10 09:39:00
2710973smart watch17012026-02-11 10:50:00

users

Columns: user_id INTEGER, username TEXT, email TEXT, signup_date TEXT, account_status TEXT, age_bucket TEXT

users: 10 of 200 rows
user_idusernameemailsignup_dateaccount_statusage_bucket
100alicealice@example.com2025-02-02inactive25-34
197aaron42aaron42@example.com2026-03-03suspended35-44
294 ameliaamelia@example.com2024-04-04pending_verification45-54
391arjun arjun@example.com2025-05-05active55-64
488ava99ava99@example.com2026-06-06inactive65+
585andrew_kandrew_k@example.com2024-07-07suspendedNULL
682anikaanika@example.com2025-08-08 16:34:00pending_verification18-24
779aidenaiden@example.com2026-09-09 14:53:00active25-34
876aria_baria_b@example.com2024-10-10inactive35-44
973brianbrian@example.com2025-11-11suspended45-54

Expected output

First 5 of 128 rows
query_iduser_idsearch_termresults_countclicked_resultquery_time
2071100laptop deals1722026-02-02 01:11:00
2142197phone case iphone 153432026-03-03 02:22:00
2213294usb-c cable 6ft51NULL2026-04-04 03:33:00
2355488mechanical keyboard8562026-06-06 05:55:00
24265854k monitor102NULL2026-07-07 06:06:00

Worked solution and explanation

What this really is

This is a two-part identity filter dressed up as a search-quality report. The join to users feels like it already means 'users who have an email on file', and that feeling is the trap. An inner join matches on user_id, not on email, so a user row whose email is NULL joins just as happily as one with an address. Anyone can write the join. What separates candidates is the explicit u.email IS NOT NULL that the join cannot express, plus the results_count > 0 gate. Skip the email test and every search from an emailless user leaks into a report that was meant to hold only identifiable people.

Step 1: Join search_queries to users on user_id

A search row carries no email, so the join is the only way to see one. As a bonus, an inner join drops the anonymous searches whose user_id is NULL, because NULL never equals anything. That is the business rule (no person, not identifiable), so reaching for a LEFT JOIN here would be wrong.

Step 2: Test email explicitly

A matched user row is not proof of an address. On this data a slice of users have a NULL email, and they own searches. Only u.email IS NOT NULL removes them, and no join condition on user_id can do that job.

Step 3: Keep searches that returned something

sq.results_count > 0 keeps searches with at least one result. It also quietly drops rows where results_count is NULL, since a comparison with NULL is never true. That is the right reading: an unknown count is not evidence that results came back.

Step 4: Return the search columns only

The ask is search query details, so project the six search_queries columns with the sq. prefix. Leaving email or username out keeps the output in the shape the preview shows and avoids an ambiguous user_id.

Searches by users with an email, results only
SELECT sq.query_id, sq.user_id, sq.search_term, sq.results_count, sq.clicked_result, sq.query_time
FROM search_queries sq
JOIN users u ON sq.user_id = u.user_id
WHERE u.email IS NOT NULL AND sq.results_count > 0
Join alone
JOIN users u ON sq.user_id = u.user_id keeps every search whose user exists, including users with a NULL email. The row count looks plausible, which is why nobody notices.
Join plus the email test
Adding u.email IS NOT NULL removes exactly the emailless users. The result shrinks to people the team can actually identify, which is the whole point of the report.

Common follow-up questions