Second Fiddle

A hard SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
hard
Seniority
L4
Asked in
Vesta Innovations

Problem

An analyst sizes up each content format in content_items by how many items registered account holders published, so an item whose creator_id has no match in users adds nothing to its format's total. For the format holding the second-highest total (every format, if several tie there), return the full record of each of its items, whoever created it, lowest content_id first.

The spotlight finds number one. The story is in what comes right after.

Tables

content_items

Columns: content_id INTEGER, title TEXT, content_type TEXT, duration_seconds INTEGER, creator_id INTEGER, publish_date TEXT

content_items: 10 of 200 rows
content_idtitlecontent_typeduration_secondscreator_idpublish_date
243The Ultimate Guide to AI TrendsarticleNULL1972026-02-02
286Top 10 Mobile Appspodcast1542942025-03-03
329Understanding Machine Learning [DRAFT]short2013912026-04-04
372Mastering Tech Startupslivestream2484882025-05-05
415Introduction to Cybersecurityvideo2955852026-06-06
458Deep Dive: Cloud ComputingarticleNULL6822025-07-07
501Behind the Scenes of Product Managementpodcast3897792026-08-08
544Breaking Down DevOpsshort4368762025-09-09
587Exploring Web Developmentlivestream483NULL2026-01-10
630How to Data Sciencevideo53010702025-11-11

users

Columns: user_id INTEGER, username TEXT, email TEXT, signup_date TEXT, account_status TEXT, age_bucket TEXT

users: 10 of 200 rows
user_idusernameemailsignup_dateaccount_statusage_bucket
100alicealice@example.com2025-02-02inactive25-34
197aaron42aaron42@example.com2026-03-03suspended35-44
294 ameliaamelia@example.com2024-04-04pending_verification45-54
391arjun arjun@example.com2025-05-05active55-64
488ava99ava99@example.com2026-06-06inactive65+
585andrew_kandrew_k@example.com2024-07-07suspendedNULL
682anikaanika@example.com2025-08-08 16:34:00pending_verification18-24
779aidenaiden@example.com2026-09-09 14:53:00active25-34
876aria_baria_b@example.com2024-10-10inactive35-44
973brianbrian@example.com2025-11-11suspended45-54

Expected output

First 5 of 40 rows
content_idtitlecontent_typeduration_secondscreator_idpublish_date
372Mastering Tech Startupslivestream2484882025-05-05
587Exploring Web Developmentlivestream483NULL2026-01-10
802Mastering Tech Startupslivestream71814582025-03-15
1017Exploring Web Developmentlivestream95319432026-02-20
1232Mastering Tech Startupslivestream118824282025-01-25

Worked solution and explanation

What this really is

Strip the business framing and this is a two-step ranking problem with two separate traps stacked on top of each other. First trap: do you know what DENSE_RANK does that ROW_NUMBER does not when two content types share the exact same count? Second, subtler trap: the registered-creator filter decides WHICH type places second, but it does not decide which rows come back. The question asks for every item of the winning type, whoever published it. Grab 'the second one' with ROW_NUMBER, or re-apply the creator filter on the way out, and the query still runs clean while the answer is quietly wrong.


Break down the requirements

Step 1: Scope to registered creators (for counting only)

Scope content_items to rows whose creator_id appears in users, via WHERE creator_id IN (SELECT user_id FROM users). Content from unregistered creators, and the null creator_id, drops out before any counting happens. This filter exists ONLY to decide the standings, so keep it confined to the counting step.

Step 2: Count per type and rank

GROUP BY content_type with COUNT(*) to get per-type volume, then assign DENSE_RANK() OVER (ORDER BY COUNT(*) DESC). Using DENSE_RANK rather than ROW_NUMBER is what lets tied types share a rank.

Step 3: Keep the second rank

Filter the ranked types to rnk = 2. Because DENSE_RANK gives every tied type the same value, this naturally keeps all types sitting at second place, not just one.

Step 4: Return the full records

Join the qualifying type(s) back to the FULL content_items table, not the filtered set, and sort by content_id, which is unique, so the order is fully determined. Because the creator filter lived only inside the counting step, items from unregistered or null creators reappear here as long as their type placed second. The livestream with a null creator_id (content_id 587) is exactly such a row, and it belongs in the output.


The solution

Count under the creator filter, rank with `DENSE_RANK`, then rejoin the full table
WITH type_counts AS (
    SELECT
        content_type,
        COUNT(*) AS cnt,
        DENSE_RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk
    FROM content_items
    WHERE creator_id IN (SELECT user_id FROM users)
    GROUP BY content_type
)
SELECT ci.*
FROM content_items ci
INNER JOIN type_counts tc ON ci.content_type = tc.content_type
WHERE tc.rnk = 2
ORDER BY ci.content_id

Common follow-up questions