Error Category Breakdown

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
City and County of San Francisco

Problem

Each row of err_tracks is one tracked error: its err_type was never normalized for letter case, and its count column holds how many times that error fired. Put every track into a 'timeout' category when its error type mentions a timeout, 'memory' when it mentions memory, and 'other' otherwise, and report how many tracks (not occurrences) land in each category.

Postmortem time. Categorize the errors.

Tables

err_tracks

Columns: err_id INTEGER, err_type TEXT, message TEXT, svc_name TEXT, severity TEXT, count INTEGER, first_at TEXT

err_tracks: 10 of 200 rows
err_iderr_typemessagesvc_nameseveritycountfirst_at
137TypeErrorCannot read property of undefinedpayment-apierror82026-02-02 01:11:00
174ConnectionTimeoutConnection timed out after 30suser-svcwarning152026-03-03 02:22:00
211OutOfMemoryHeap space exhaustedsearch-apiinfo222026-04-04 03:33:00
248FileNotFoundFile /tmp/data.csv not foundgatewayFatal292026-05-05 04:44:00
285PermissionDeniedAccess denied for user rootworkerERROR362026-06-06 05:55:00
322RateLimitExceededToo many requests from 10.0.0.1auth-svcfatal432026-07-07 06:06:00
359ParseErrorMalformed JSON in request bodypayment-apierror502026-08-08 07:17:00
396nullpointerexceptionStack overflow in recursive calluser-svcwarning572026-09-09 08:28:00
433TYPEERRORDivision by zerosearch-apiinfo642026-01-10 09:39:00
470NullPointerExceptionUnexpected null value at line 42gatewayFatalNULL2026-02-11 10:50:00

Expected output

First 3 of 3 rows
error_categorytrack_count
memory20
other160
timeout20

Worked solution and explanation

What this really is

This is a label you have to invent, dressed up as an error report. No column holds 'timeout' or 'memory'. You build that label row by row from err_type, then count rows under it. Writing a CASE is the easy part. The two traps are the ones the statement hints at. First, err_type is spelled in mixed case ('ConnectionTimeout', 'OutOfMemory', 'TYPEERROR'), so a case-sensitive pattern like '%timeout%' matches nothing and every row collapses into 'other'. Second, the table has a column named count, and SUM(count) gives occurrence totals instead of track counts.

Step 1: Normalize before you match

Wrap the column as LOWER(err_type) before any LIKE. 'ConnectionTimeout' only contains 'timeout' after lowercasing. Without that, the result is a single 'other' row holding all 200 tracks. It is a valid query that answers nothing.

Step 2: Derive the label with CASE

Test timeout first, then memory, and send everything else to ELSE 'other'. Branch order matters: CASE returns the first branch that matches. An error type that mentioned both a timeout and memory would count as a timeout.

Step 3: Group on the label, count rows

Group by the derived error_category, not by err_type. Grouping by the raw column gives one row per spelling. Count with COUNT(*), because each row is one track. count is an occurrence tally, and it is also NULL on some rows.

Bucket, then count
SELECT
    CASE
        WHEN LOWER(err_type) LIKE '%timeout%' THEN 'timeout'
        WHEN LOWER(err_type) LIKE '%memory%' THEN 'memory'
        ELSE 'other'
    END AS error_category,
    COUNT(*) AS track_count
FROM err_tracks
GROUP BY error_category
Looks right
err_type LIKE '%timeout%' with SUM(count). On an engine with case-sensitive LIKE, no row matches. Even when rows do match, the numbers are occurrences, and rows with a NULL count drop out silently.
Is right
LOWER(err_type) LIKE '%timeout%' with COUNT(*). Matching ignores casing, and every track counts exactly once whatever its occurrence tally.

Common follow-up questions