Double Take

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
L3
Asked in
Google

Problem

A downstream team flagged that the data quality checks table has rows repeating the same table-and-column combination. Surface every pair that appears more than once along with how many times it shows up, worst offenders first. Include each pair's standing among the offenders and its share of all the duplicated records.

Passed QA twice. That's the problem.

Tables

dq_checks

Columns: check_id INTEGER, tbl_name TEXT, col_name TEXT, rule TEXT, passed INTEGER, fail_pct REAL, run_at TEXT, severity TEXT

dq_checks: 10 of 200 rows
check_idtbl_namecol_namerulepassedfail_pctrun_atseverity
131usersemailunique1NULL2026-02-02 01:00:00high
162productsamountrange1NULL2026-03-03 02:00:00medium
193transactionsstatusformat1NULL2026-04-04 03:00:00low
224eventscreated_atreferential1NULL2026-05-05 04:00:00Critical
255sessionspricefreshness0152026-06-06 05:00:00HIGH
286ad_impressionsregionNot_Null1NULL2026-07-07 06:00:00critical
317ordersuser_idUNIQUE102026-08-08 07:00:00high
348usersemailnot_null1NULL2026-09-09 08:00:00medium
379productsamountunique1NULL2026-01-10 09:00:00low
410transactionsstatusrange0302026-02-11 10:00:00Critical

Expected output

First 5 of 7 rows
tbl_namecol_nameduplicate_countdup_rankpct_of_dups
productsamount30115
usersemail30115
ad_impressionsregion28314
eventscreated_at28314
ordersuser_id28314

Worked solution and explanation

The trap hiding in a data quality problem

This is a GROUP BY / HAVING duplicate hunt wearing a data-quality badge. The real question being probed: do you know that a duplicate here is defined by exactly two columns, tbl_name and col_name, and nothing else? Anyone can write COUNT(*) with a HAVING filter. The tell is what you put in the GROUP BY. Drop in rule or run_at because they feel like part of the row and every group collapses to size one, so you report zero duplicates and confidently hand back an empty result to a team that can see the repeats with their own eyes.


Break down the requirements

Step 1: Isolate the duplicate key

Isolate the duplicates: GROUP BY tbl_name, col_name and keep only the groups with COUNT(*) > 1, capturing the duplicate_count for each offending table-and-column pair. Materialize this as the pair_counts CTE so the analytic step operates on the filtered duplicate set only.

Step 2: Rank the worst offenders

Rank the offenders: apply RANK() OVER (ORDER BY duplicate_count DESC) so the worst-duplicated pairs surface first and ties share a position, telling the downstream team which combinations to triage initially.

Step 3: Quantify each pair's share

Quantify the burden share: divide each pair's duplicate_count by SUM(duplicate_count) OVER () (the total across all duplicate pairs) and ROUND to 2 decimals to express each pair's percentage of the overall duplicate volume.


The solution

GROUP BY with HAVING for duplicate detection
WITH pair_counts AS (
    SELECT tbl_name, col_name, COUNT(*) AS duplicate_count
    FROM dq_checks
    GROUP BY tbl_name, col_name
    HAVING COUNT(*) > 1
)
SELECT
    tbl_name,
    col_name,
    duplicate_count,
    RANK() OVER (ORDER BY duplicate_count DESC) AS dup_rank,
    ROUND(100.0 * duplicate_count / SUM(duplicate_count) OVER (), 2) AS pct_of_dups
FROM pair_counts
ORDER BY duplicate_count DESC, tbl_name, col_name

Common follow-up questions