Keyword-Based User Search
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
Problem
We're running a search-quality audit and need the shoppers who searched for the hardware itself: a desk, a monitor, a cable, or a mouse. Return the unique user IDs, but leave out the accessory searches such as desk mats, monitor arms, and cable-management trays.
The search terms reveal intent.
Tables
search_queries
Columns: query_id INTEGER, user_id INTEGER, search_term TEXT, results_count INTEGER, clicked_result INTEGER, query_time TEXT
| query_id | user_id | search_term | results_count | clicked_result | query_time |
|---|---|---|---|---|---|
| 2071 | 100 | laptop deals | 17 | 2 | 2026-02-02 01:11:00 |
| 2142 | 197 | phone case iphone 15 | 34 | 3 | 2026-03-03 02:22:00 |
| 2213 | 294 | usb-c cable 6ft | 51 | NULL | 2026-04-04 03:33:00 |
| 2284 | NULL | gaming mouse | 68 | 5 | 2026-05-05 04:44:00 |
| 2355 | 488 | mechanical keyboard | 85 | 6 | 2026-06-06 05:55:00 |
| 2426 | 585 | 4k monitor | 102 | NULL | 2026-07-07 06:06:00 |
| 2497 | 682 | standing desk | 119 | 8 | 2026-08-08 07:17:00 |
| 2568 | NULL | webcam 1080p | 136 | 9 | 2026-09-09 08:28:00 |
| 2639 | 876 | bluetooth speaker | 153 | NULL | 2026-01-10 09:39:00 |
| 2710 | 973 | smart watch | 170 | 1 | 2026-02-11 10:50:00 |
Expected output
| user_id |
|---|
| 294 |
| NULL |
| 585 |
| 682 |
| 2234 |
Worked solution and explanation
What this really is
This is a substring-containment filter wearing a product-intent costume. The real question: do you remember that LIKE '%desk%' matches the letters 'desk' wherever they sit, so it grabs 'desk mat' right alongside 'standing desk'? Anyone can write the four OR LIKE '%kw%' conditions. What separates candidates is subtracting the accessory rows that share a product word, and keeping that subtraction from binding to the wrong term. Miss it and every accessory shopper, exactly the cohort the audit was told to drop, lands in your unique-user list.
Break down the requirements
Step 1: Build the inclusion OR chain
Join four search_term LIKE '%kw%' conditions with OR. Containment is the point: 'usb-c cable 6ft' and 'gaming mouse' never equal a bare product word, so they only match through the wildcard.
Step 2: Parenthesize the OR group
The accessory exclusion is an AND against the whole inclusion group. Without the parentheses, AND binds tighter than OR, so the exclusions guard only the mouse searches and 'desk mat' and 'monitor arm' walk straight back in.
Step 3: Subtract the accessory terms
'desk mat', 'monitor arm' and 'cable management' each contain a product word, so they satisfy a positive pattern and must be removed by hand: NOT LIKE '%mat%', NOT LIKE '%arm%', NOT LIKE '%management%'. This is the load-bearing step. On this seed each of those terms belongs to a different set of users, so every exclusion changes the answer.
Step 4: Collapse to unique users
Use SELECT DISTINCT user_id. A shopper shows up on several matching rows, and the audit wants the set of users, not the list of queries. Anonymous rows where user_id is NULL stay, because nothing filters them out.
The solution
SELECT DISTINCT user_id
FROM search_queries
WHERE (
search_term LIKE '%desk%'
OR search_term LIKE '%monitor%'
OR search_term LIKE '%cable%'
OR search_term LIKE '%mouse%'
)
AND search_term NOT LIKE '%mat%'
AND search_term NOT LIKE '%arm%'
AND search_term NOT LIKE '%management%'- Positive-only filter
- Four
LIKEconditions joined withOR. It matches 'standing desk' and also 'desk mat', 'monitor arm' and 'cable management', so the accessory shoppers are returned as hardware shoppers. - With accessory exclusions
- The same
ORgroup in parentheses, thenAND ... NOT LIKEon '%mat%', '%arm%' and '%management%'. Only the shoppers who searched for the product itself remain.
Common follow-up questions
Common follow-up questions
- Why not `WHERE search_term IN ('desk','monitor','cable','mouse')`? (Tests whether they know `IN` is exact equality, not substring containment.)
- How do you keep `NOT LIKE '%arm%'` from also dropping 'warm blanket' or 'alarm clock'? (Probes word-boundary matching or a move to tokenized search.)
- Search terms start arriving in mixed case from a new client. What changes? (Tests whether they know `LIKE` case sensitivity differs by engine and normalise the column once.)
- What if the audit also needs the count of matching searches per user? (Forces a switch from `SELECT DISTINCT` to `GROUP BY user_id` with `COUNT(*)`.)
- Could you push the product-vs-accessory rule into the data pipeline instead of the query? (Tests whether they see it as a classification computed once upstream.)