Features With Missing Values

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
Asked in
Airbnb

Problem

Our model training job keeps crashing on features that never had an average value recorded. Pull every one of those records from ml_features, with the feature names in alphabetical order.

Missing data in the features.

Tables

ml_features

Columns: feat_id INTEGER, feat_name TEXT, dtype TEXT, avg_val REAL, null_pct REAL, updated TEXT, source TEXT

ml_features: 10 of 200 rows
feat_idfeat_namedtypeavg_valnull_pctupdatedsource
141login_countint647.332026-02-02transactions
182cart_valuefloat3214.662026-03-03page_views
223page_dwellstring21.992026-04-04ad_impressions
264click_rateboolean29.2122026-05-05NULL
305days_activeFloat6436.5152026-06-06search_queries
346avg_orderINT6443.8182026-07-07orders
387session_lenfloat6451.1212026-08-08NULL
428scroll_pctint6458.4242026-09-09user_sessions
469bounce_cntfloat3265.7NULL2026-01-10transactions
510user_agestring73302026-02-11page_views

Expected output

First 5 of 16 rows
feat_idfeat_namedtypeavg_valnull_pctupdatedsource
1576avg_orderint64NULLNULL2026-01-09NULL
592cart_valueFloat64NULL362026-04-13NULL
1084click_ratestringNULL722026-07-25user_sessions
2068scroll_pctINT64NULL442026-04-21user_sessions
2560user_agebooleanNULL802026-07-05NULL

Worked solution and explanation

This is a three-valued-logic check dressed up as a debugging ticket. Finding the right table is easy. What separates candidates is writing avg_val IS NULL instead of avg_val = NULL, and aiming the test at avg_val rather than the null_pct column whose name screams 'null'. Get the first one wrong and the query runs cleanly and returns zero rows. The team then concludes the feature store is fine while training keeps crashing.

The reasoning

Step 1: Pick the column that is actually missing

'Never had an average value recorded' means avg_val holds the NULL marker. null_pct is a statistic about the feature, not a hole in this record. source is also empty on 50 rows. Filtering either of those returns a different, wrong set.

Step 2: Test for the marker, not a value

NULL is not a value you can compare against. avg_val = NULL evaluates to UNKNOWN on every row, and WHERE keeps only TRUE. IS NULL is the predicate built to ask whether the marker is there, and on the seed it catches 16 of the 200 rows.

Step 3: Return the whole record, sorted by feat_name

The team needs the full row to trace each broken feature back to its source and dtype, so all seven columns come back. Names repeat (there are four 'avg_order' records, for example). The order only promises names A to Z, so rows that share a name can come in any order.

Records with no average value, by feature name
SELECT feat_id, feat_name, dtype, avg_val, null_pct, updated, source
FROM ml_features
WHERE avg_val IS NULL
ORDER BY feat_name
The version that looks right
SELECT feat_id, feat_name, dtype, avg_val, null_pct, updated, source
FROM ml_features
WHERE avg_val = NULL
ORDER BY feat_name

Runs without error and returns nothing: avg_val = NULL is never TRUE.

Common follow-up questions