Both Ends of the Pipe
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
- TripAdvisor
Problem
A release manager is auditing deploy_logs, where environment and author names were typed with inconsistent casing: 'Production' and 'production' are one environment, and 'Alice' and 'alice' are one author. List, alphabetically, each author who has deployed to at least two of the three standing environments, dev, staging and production, along with how many of them they reached.
Dev and prod, both touched by the same hand. Who are they?
Tables
deploy_logs
Columns: log_id INTEGER, svc_name TEXT, version TEXT, env_name TEXT, status TEXT, deploy_at TEXT, dur_secs INTEGER, author TEXT
| log_id | svc_name | version | env_name | status | deploy_at | dur_secs | author |
|---|---|---|---|---|---|---|---|
| 131 | payment-api | v1.0.2 | staging | failed | 2026-02-02 01:11:00 | 23 | bob |
| 162 | user-svc | v1.1.0 | dev | rolled_back | 2026-03-03 02:22:00 | 36 | charlie |
| 193 | search-api | 2.0.0 | canary | in_progress | 2026-04-04 03:33:00 | 49 | dana |
| 224 | gateway | v2.1.0 | Production | Success | 2026-05-05 04:44:00 | 62 | eve |
| 255 | notif-svc | 2.1.1 | STAGING | FAILED | 2026-06-06 05:55:00 | 75 | frank |
| 286 | analytics | v3.0.0-rc1 | production | success | 2026-07-07 06:06:00 | 88 | Alice |
| 317 | ml-serving | v1.0.3 | staging | failed | 2026-08-08 07:17:00 | NULL | BOB |
| 348 | auth-svc | v1.0.1 | dev | Rolled_Back | 2026-09-09 08:28:00 | 114 | alice |
| 379 | Payment-API | v1.0.2 | canary | in_progress | 2026-01-10 09:39:00 | 127 | bob |
| 410 | user-svc | v1.1.0 | Production | Success | 2026-02-11 10:50:00 | 140 | charlie |
Expected output
| author | env_count |
|---|---|
| alice | 2 |
| charlie | 2 |
| eve | 2 |
Worked solution and explanation
What this is really asking
This is a distinct count over two dirty keys dressed up as a release audit. Anyone can filter to dev, staging and production and count. What separates candidates is noticing that the casing mess sits on both sides of the grouping. Every author who reached production has rows under both 'production' and 'Production', and 'alice' also deploys as 'Alice'. If you fold only one of the two keys, you either count production twice or report one person as two rows. Either way the at-least-two test ends up judging the wrong numbers.
Step 1: Fold the environment once and use that fold everywhere
Compare UPPER(env_name) against the upper-case literals 'DEV', 'STAGING' and 'PRODUCTION'. That keeps the 'Production', 'STAGING' and 'Dev' rows and drops canary. The same UPPER(env_name) has to go inside the count, or 'production' and 'Production' come back as two environments.
Step 2: Fold the author before grouping
GROUP BY LOWER(author) merges 'Alice' and 'alice' into one person. Select the same LOWER(author) so the name you report matches the grain you grouped at. Grouping on the raw author reports one person as two rows, each judged on only part of their history.
Step 3: Count stages, then test the count
COUNT(DISTINCT UPPER(env_name)) is how many of the three stages an author reached, and HAVING COUNT(DISTINCT UPPER(env_name)) >= 2 keeps the authors who span at least two. 'bob', 'dana' and 'frank' only ever deployed to staging, so they arrive with 1 and drop out.
SELECT LOWER(author) AS author,
COUNT(DISTINCT UPPER(env_name)) AS env_count
FROM deploy_logs
WHERE UPPER(env_name) IN ('DEV', 'STAGING', 'PRODUCTION')
GROUP BY LOWER(author)
HAVING COUNT(DISTINCT UPPER(env_name)) >= 2
ORDER BY author;- Half-folded
WHERE UPPER(env_name) IN (...)withCOUNT(DISTINCT env_name)andGROUP BY author. 'alice' and 'Alice' arrive as separate rows, and each counts 'production' and 'Production' as different environments, so they report 3 and 4 environments out of a possible three.- Folded on both keys
UPPER(env_name)in both the filter and the count, andLOWER(author)in both the select and the grouping. Three authors come back, each with 2, and 'bob', 'dana' and 'frank' are filtered out by the count.
Common follow-up questions
Common follow-up questions
- What if `env_name` also carries stray whitespace from a CSV ingest? (Wrap the fold in `TRIM`, and ideally clean the value at ingest so downstream queries stop paying for it.)
- Now require dev and production specifically, not any two stages? (A count of stages cannot tell you which two were reached; each required stage has to be checked on its own.)
- How would you list authors who never made it past staging? (Same grain, opposite test: keep the authors whose folded environments never include 'PRODUCTION'.)