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

deploy_logs: 10 of 200 rows
log_idsvc_nameversionenv_namestatusdeploy_atdur_secsauthor
131payment-apiv1.0.2stagingfailed2026-02-02 01:11:0023bob
162user-svcv1.1.0devrolled_back2026-03-03 02:22:0036charlie
193search-api2.0.0canaryin_progress2026-04-04 03:33:0049dana
224gatewayv2.1.0ProductionSuccess2026-05-05 04:44:0062eve
255notif-svc2.1.1STAGINGFAILED2026-06-06 05:55:0075frank
286analyticsv3.0.0-rc1productionsuccess2026-07-07 06:06:0088Alice
317ml-servingv1.0.3stagingfailed2026-08-08 07:17:00NULLBOB
348auth-svcv1.0.1devRolled_Back2026-09-09 08:28:00114alice
379Payment-APIv1.0.2canaryin_progress2026-01-10 09:39:00127bob
410user-svcv1.1.0ProductionSuccess2026-02-11 10:50:00140charlie

Expected output

First 3 of 3 rows
authorenv_count
alice2
charlie2
eve2

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.

The folded stage count
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 (...) with COUNT(DISTINCT env_name) and GROUP 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, and LOWER(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