Flag Check

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

Problem

A release engineer sweeping feat_flags before the next rollout wants to know: which owners are holding flags with no rollout value on file, how many such flags does each hold, and how many of those are switched on anyway?

Which flags are actually live?

Tables

feat_flags

Columns: flag_id INTEGER, flag_name TEXT, enabled INTEGER, rollout REAL, owner TEXT, created TEXT, updated TEXT

feat_flags: 10 of 200 rows
flag_idflag_nameenabledrolloutownercreatedupdated
131new_checkout0NULLengineering2025-02-022026-02-02
162beta_search0NULLgrowth2025-03-032026-03-03
193ai_recs139platform2025-04-042026-04-04
224live_chat0NULLmobile2025-05-052026-05-05
255video_upload0NULLdata2025-06-062026-06-06
286two_factor178product2025-07-072026-07-07
317bulk_export0NULLengineering2025-08-082026-08-08
348new_dashboard0NULLgrowth2025-09-092026-09-09
379mobile_v2117platform2025-10-102026-01-10
410dark_mode0NULLmobile2025-11-112026-02-11

Expected output

First 4 of 4 rows
ownerunconfigured_flagsenabled_count
data320
engineering340
growth340
mobile340

Worked solution and explanation

What this is really asking

This is a NULL-selection problem wearing a release-audit costume. The rollup per owner is the easy part; anyone writes GROUP BY owner. The part that separates candidates is how you reach the flags with no rollout. Every aggregate you might point at rollout skips NULLs by design, so COUNT(rollout) reports zero unconfigured flags for everyone, and rollout = NULL matches no rows at all. Either way the release team hears that nobody has half-configured flags, while most owners are sitting on dozens.


Building it

Step 1: Select the rows with nothing in rollout

The unconfigured flags exist only as NULLs in rollout, so they have to be picked out as rows before anything aggregates. WHERE rollout IS NULL does it; IS NULL is the only test that is true for a missing value.

Step 2: Roll up per owner

GROUP BY owner collapses the filtered rows to one line per owner. COUNT(*) counts rows, not values, so it counts exactly the flags the filter kept.

Step 3: Count the switched-on ones with SUM(enabled)

enabled is stored as 0 or 1, so SUM(enabled) is the number switched on. No CASE needed.

One pass, NULLs selected before grouping
SELECT owner, COUNT(*) AS unconfigured_flags, SUM(enabled) AS enabled_count FROM feat_flags WHERE rollout IS NULL GROUP BY owner

The filter runs first, so both counts describe the same unconfigured set.

Counting the column
COUNT(rollout) or COUNT(*) - COUNT(rollout) in the select list tries to measure NULLs through an aggregate. The first is always zero here; the second works but hides the intent and cannot scope SUM(enabled) to the same flags.
Counting the rows
WHERE rollout IS NULL keeps only the unconfigured rows, so COUNT(*) and SUM(enabled) both describe exactly that set.

Common follow-up questions