The Words That Page Us
A hard SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- hard
- Seniority
- L4
- Asked in
- Yelp
Problem
During an incident review, on-call wants every chat message mentioning 'latency', 'down', 'back', or 'pipeline' lined up against the error tracking entries logged in the same month. Show the channel, the message text, and the severity of the error it matched.
Certain words trigger an investigation.
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 |
err_tracks
Columns: err_id INTEGER, err_type TEXT, message TEXT, svc_name TEXT, severity TEXT, count INTEGER, first_at TEXT
| err_id | err_type | message | svc_name | severity | count | first_at |
|---|---|---|---|---|---|---|
| 137 | TypeError | Cannot read property of undefined | payment-api | error | 8 | 2026-02-02 01:11:00 |
| 174 | ConnectionTimeout | Connection timed out after 30s | user-svc | warning | 15 | 2026-03-03 02:22:00 |
| 211 | OutOfMemory | Heap space exhausted | search-api | info | 22 | 2026-04-04 03:33:00 |
| 248 | FileNotFound | File /tmp/data.csv not found | gateway | Fatal | 29 | 2026-05-05 04:44:00 |
| 285 | PermissionDenied | Access denied for user root | worker | ERROR | 36 | 2026-06-06 05:55:00 |
| 322 | RateLimitExceeded | Too many requests from 10.0.0.1 | auth-svc | fatal | 43 | 2026-07-07 06:06:00 |
| 359 | ParseError | Malformed JSON in request body | payment-api | error | 50 | 2026-08-08 07:17:00 |
| 396 | nullpointerexception | Stack overflow in recursive call | user-svc | warning | 57 | 2026-09-09 08:28:00 |
| 433 | TYPEERROR | Division by zero | search-api | info | 64 | 2026-01-10 09:39:00 |
| 470 | NullPointerException | Unexpected null value at line 42 | gateway | Fatal | NULL | 2026-02-11 10:50:00 |
Expected output
| channel | content | severity |
|---|---|---|
| #engineering | Anyone seeing increased latency? | error |
| #engineering | Anyone seeing increased latency? | Fatal |
| #random | Dashboard is down | info |
| #deployments | Can someone check the pipeline? | error |
| #data-team | Rolling back to v2.0 | warning |
Worked solution and explanation
Why this problem exists in real interviews
Strip the incident-review costume and this is a derived-string equi-join hiding a many-to-many explosion. The only thing tying a chat message to an error is the calendar month you carve out of two timestamp strings, so SUBSTR(sent_at, 1, 7) isn't formatting, it IS the join key. Anyone can write the OR-chain keyword filter; what separates candidates is naming, out loud, that equal months pair every matching message with every same-month error before they hit run. Miss it and the result balloons past 100M rows per month bucket while partition pruning quietly dies, because the planner cannot push a SUBSTR expression down to the partition column.
Break down the requirements
Step 1: Filter messages by keyword
OR-chain of cm.content LIKE on '%latency%', '%down%', '%back%', '%pipeline%'. Leading wildcards mean no btree index helps. Wrap in LOWER() if the engine is case-sensitive.
Step 2: Define same-month
SUBSTR(cm.sent_at, 1, 7) = SUBSTR(et.first_at, 1, 7) gives 'YYYY-MM'. Works on ISO strings or timestamps cast to text. Both sides are derived, so neither partition key gets pruned.
Step 3: Project the three columns
cm.channel, cm.content, et.severity. No aggregation in the spec, so duplicates from the many-to-many join land in the result set.
Step 4: Decide on shape
One chat row pairs with every same-month error. Confirm with the interviewer: per-message-per-error, or DISTINCT on (channel, content, severity), or one row per message with max severity.
The solution
SELECT cm.channel, cm.content, et.severity
FROM chat_msgs cm
INNER JOIN err_tracks et
ON SUBSTR(cm.sent_at, 1, 7) = SUBSTR(et.first_at, 1, 7)
WHERE cm.content LIKE '%latency%'
OR cm.content LIKE '%down%'
OR cm.content LIKE '%back%'
OR cm.content LIKE '%pipeline%'COMMON FOLLOW-UP QUESTIONS
Common follow-up questions
- How would you collapse to one row per message with the highest severity? (Tests window functions or GROUP BY with a severity rank.)
- Rewrite the month join so partition pruning actually fires. (Probes whether you reach for `DATE_TRUNC('month', ...)` and range predicates instead of `SUBSTR`.)
- How do you make the keyword filter case-insensitive across Postgres and Snowflake? (Checks awareness of `LOWER()` vs `ILIKE` portability.)
- Would a tokenized full-text index change your approach at 60M rows? (Opens the door to GIN, search services, or precomputed keyword flags.)