ETL Testing Interview Questions for 2026: Test Design, Validation SQL, and Answers That Hold Up
Sixteen interview questions covering what ETL testers are actually hired for — count, duplicate, referential and transformation checks, source-to-target mapping tests, SCD2 verification, defect classification, and reconciliation at scale. Written from the QA seat, not the pipeline-design seat.
By Durgesh Yadav — Senior Data Engineer @ 7-Eleven · Updated 2026-07-25. Preparation guidance, not a hiring guarantee.
What questions are asked in an ETL testing interview?
ETL testing interviews focus on validation checks — row counts, duplicates, nulls, referential integrity, transformation rules — plus writing SQL to compare source and target, deriving test cases from a source-to-target mapping document, testing incremental loads and SCD Type 2 dimensions, classifying defects correctly, and reconciling large tables where row-by-row comparison is impractical.
ETL testing interviews are SQL interviews wearing a QA hat. The interviewer wants evidence of three things. First, that you can turn a source-to-target mapping document into a concrete test suite — most candidates can name "count check, duplicate check" but stall when handed an actual mapping sheet and asked what they would test first. Second, that you can write the validation SQL live: orphan checks with LEFT JOIN, duplicate detection with GROUP BY and HAVING, both directions of EXCEPT, and window functions for SCD history. Third — and this separates 2-6-year candidates from freshers — judgment: what you check at 500 million rows when row-by-row comparison is off the table, how you classify a defect so it reaches the right owner, and how you regression-test a change without reloading the world. Note the difference from data engineering rounds: those probe pipeline design (CDC, idempotency, orchestration); ETL testing rounds probe verification of someone else's pipeline.
Deriving test cases from a mapping document, live
Validation SQL written from memory, not described
Scale judgment: what replaces row-by-row at 500M rows
Verification mindset — distinct from pipeline-design rounds
How to Prepare
Build a two-table sandbox — any two schemas in Postgres or MySQL will do — and practice the whole loop: write a small mapping sheet, load "source" into "target" with a deliberate bug, then catch it with SQL. Drill the six core check patterns until they are muscle memory: counts per partition, duplicates on a business key, null checks on mandatory columns, orphan checks, EXCEPT in both directions, and independent recomputation of one derived column. Then rehearse the scenario layer: list the delta-load cases (insert, update, delete, boundary timestamp, rerun) and the SCD2 structural checks, because those get asked as "how would you test this" rather than "write the query". Finally, prepare defect stories from real work — one per category: a source-data issue, a spec ambiguity, a genuine code bug, an environment problem. Experienced candidates are judged more on those stories and their classification instincts than on syntax.
Two-table sandbox: seed a bug, catch it with SQL
Six check patterns drilled to muscle memory
Delta-load and SCD2 scenarios rehearsed verbally
One real defect story per taxonomy category
Common Mistakes That Sink Candidates
The most common failure is trusting counts: declaring a load verified because source and target row counts match, with no answer for truncation, wrong-row updates, or offsetting duplicate-and-missing errors. Second: tool recitation without SQL — naming testing tools you have used but freezing when asked to write the orphan check those tools generate. Third: running EXCEPT in one direction only, which finds missing rows but not invented ones, and forgetting that set operators collapse duplicates. Fourth: ignoring NULL semantics — candidates who do not know that NULL = NULL is false in a join predicate but NULLs match in EXCEPT and GROUP BY will write checks that silently pass on broken data. Fifth: treating every discrepancy as a code bug; interviewers deliberately present source-data or spec defects to see whether you classify before you blame. Finally, testing only the happy path of incremental loads — no rerun case, no boundary timestamp, no delete handling — reads as someone who has never seen a pipeline fail.
Sign-off on counts alone
One-directional EXCEPT, duplicates invisible
NULL semantics guessed, not known
Every defect blamed on code
Manual SQL vs Tool-Based Testing (and the ELT Shift)
Interviewers care about the method, not the license. Tools in the QuerySurge mould add scheduling, cross-database comparison, and reporting on top of the same primitives — counts, minus queries, aggregate profiles — so the strong answer describes the check in SQL first and the tool as automation of it. Saying "the tool validates it" without being able to write the underlying query is a red flag; the reverse — manual SQL plus a clear view of what you would automate and why — is a green one. The ELT shift matters here too: when transformation happens inside the warehouse, validation moves with it. Checks become SQL against staging and mart layers, and frameworks in the dbt-test style let developers ship assertions with the code. That raises, rather than removes, the value of an independent testing lens: dev-owned tests encode the developer's assumptions, and the classic QA questions — is the spec right, what about the reject path, what breaks at the boundary — still need someone to ask them.
Describe the check in SQL, then the tool as automation
"The tool handles it" is a red-flag answer
ELT moves validation into warehouse SQL
Dev-owned dbt-style tests are not independent verification
Question bank
16 interview questions with answers
Real questions from beginner to advanced, each with a concise model answer — practice them, then rehearse live in a mock interview.
EasyWhat is ETL testing, and how does it differ from application testing?
ETL testing verifies that data extracted from source systems lands in the target complete, accurate, and transformed exactly as the specification says. The expected result is not a screen or an API response — it is the source data plus the mapping rules, so almost every test is a SQL query comparing two datasets. Three differences from application testing stand out. First, the test oracle is the source-to-target mapping document, not a UI spec. Second, volume is a first-class concern: a check that works on 1,000 rows may be useless on 100 million. Third, many defects are not code defects at all — bad data in the source, an ambiguous mapping rule, or a mis-sequenced job can each produce wrong output with correct code. Part of the tester's job is deciding which of those it is.
EasyWhat is a source-to-target mapping document, and how do you derive test cases from it?
A source-to-target mapping (STM) document lists, for every target column: the source table and column, the data type on both sides, and the transformation rule — direct move, derived expression, lookup, default, or aggregation. It is the tester's primary requirement document. To derive test cases, work rule by rule: direct-move columns get a value comparison; derived columns get an independent recomputation of the expression; lookup columns get a join against the reference table plus an orphan check for keys that fail the lookup; default rules get cases where the source is NULL or invalid. Then add table-level cases no single mapping row implies: row counts, duplicate checks on the declared grain, referential integrity, and datatype or truncation checks where source and target types differ. If the STM is ambiguous, that is itself a defect — raise it rather than coding tests around a guess.
EasyWhat core validation checks make up a baseline ETL test suite?
Six categories. Count checks: compare source row counts — after the filters and joins the spec defines — to target counts, overall and per partition or load date. Duplicate checks: group by the declared business key and flag keys appearing more than once. Null checks: mandatory columns should contain no NULLs, and defaulting rules should have fired. Referential integrity checks: every foreign key in a fact should resolve to a dimension row, since most warehouses do not enforce constraints. Transformation checks: recompute derived columns independently and compare against the target. Datatype and truncation checks: verify precision, length, and encoding survive the move — a VARCHAR(100) to VARCHAR(50) mapping silently truncates in some configurations and errors in others. Each category maps to one or two reusable SQL patterns, which is exactly why interviewers ask you to write them live.
EasySource and target row counts match. Why is that not enough to sign off the load?
A matching count only proves the same number of rows arrived — not that they are the right rows or hold the right values. Failure modes that pass a count check: values truncated or defaulted during load; a wrong join that drops some rows and duplicates others so the totals cancel out; updates applied to the wrong rows; character-set corruption; a transformation bug that alters a derived column on every row. Counts are the cheapest check, so run them first — but sign-off needs content validation: duplicate checks on the key, column-level aggregates (SUM, MIN/MAX, distinct counts, null counts) compared between source and target, MINUS/EXCEPT comparisons on manageable volumes, and independent recomputation of transformed columns. A useful summary for the interview: counts prove completeness of volume, not correctness of content.
EasyWhich SQL constructs does an ETL tester rely on most, and why?
Five families cover most of the job. Joins — especially LEFT JOIN with WHERE right_key IS NULL, the standard orphan and missing-row pattern. Aggregation with GROUP BY and HAVING — duplicate detection via HAVING COUNT(*) > 1, and column profiling with SUM, MIN, MAX, COUNT(DISTINCT) and null counts. Set operators — MINUS or EXCEPT, run in both directions, to find rows present on only one side. Window functions — ROW_NUMBER to inspect duplicate groups or pick the latest version of a record, LAG and LEAD to test SCD date-range continuity. CASE expressions — to independently recompute mapping rules instead of re-running the developer's logic. Underpinning all of it: NULL semantics. NULL = NULL is not true in a WHERE clause, but set operators and GROUP BY treat NULLs as matching, and COUNT(column) skips them — three behaviors that cause false passes if forgotten.
MediumHow do you test for duplicate records, and how do you decide whether the defect is in the load or the source?
Start by pinning down the grain — "duplicate" is meaningless until you know what one row is supposed to represent. For business-key duplicates: SELECT key_cols, COUNT(*) FROM target GROUP BY key_cols HAVING COUNT(*) > 1. For full-row duplicates, group by all columns, or compare COUNT(*) with a distinct count over a row hash. To inspect offenders, use ROW_NUMBER() OVER (PARTITION BY key ORDER BY load_ts DESC) and pull groups larger than one — this also shows which copy the dedup logic should have kept. Then run the same check on the source: if the duplicate exists upstream, it is a source-data defect, and the question becomes whether the spec says dedupe, reject, or pass through. If the source is clean and the target is not, suspect the load — a rerun without idempotency or a join that fans out are the usual causes.
MediumExplain the MINUS/EXCEPT comparison strategy and its limitations.
The pattern: (SELECT cols FROM source_query) EXCEPT (SELECT cols FROM target_query), then the reverse direction, because EXCEPT is asymmetric — one direction finds rows missing from the target, the other finds rows the target invented. The traps are the real interview material. EXCEPT is set-based: it collapses duplicates, so a row appearing three times in source and once in target produces no difference — always pair it with count and duplicate checks. NULLs are treated as equal to each other in set operations, unlike in join predicates — usually what you want, but it should be a conscious choice. Formatting differences — trailing spaces, decimal precision, timestamp truncation — produce noisy false diffs, so cast and trim deliberately. It is expensive at volume, and it cannot run natively across two different engines; there you extract both sides into one engine or use a cross-database comparison tool. Use EXCEPT for drill-down, not as the primary check on huge tables.
MediumHow do you test referential integrity when the target warehouse does not enforce foreign keys?
Most analytical databases accept foreign key declarations but do not enforce them, so referential integrity is the tester's job. The core query: SELECT f.* FROM fact f LEFT JOIN dim d ON f.dim_key = d.dim_key WHERE d.dim_key IS NULL — any rows returned are orphans. Run it for every fact-to-dimension relationship, ideally per load rather than once. Then test the design's stated policy for failures: many pipelines route unresolvable keys to a default "unknown" member (often key -1) instead of dropping the row, so verify orphans actually land there, that the unknown member exists, and that rows are not silently discarded. Late-arriving dimensions are the subtle case: a fact can legitimately arrive before its dimension row, so check whether the spec says hold, default-and-reprocess, or reject — and write a test for that behavior, not just the happy path.
MediumHow do you validate complex transformation logic without trusting the developer's code?
The principle is independent recomputation: derive the expected value from the source yourself, using the mapping document, rather than re-running the developer's transformation — otherwise you are testing the code against itself. For a rule like "status = A if balance is positive and the account is open, else I", write a CASE expression over source columns and compare it to the target column — row by row on critical columns, sampled on the rest. For rules too complex to inline — multi-step derivations, aggregations, lookups with precedence — build a small handcrafted input dataset with a worked expected output covering every branch and boundary of the rule, push it through the pipeline in a test environment, and diff. Prioritize by risk: money amounts, keys, and status fields get full-volume verification; descriptive text can be sampled. Record which STM rule each test covers, so coverage stays auditable against the spec.
MediumHow do you design test cases for an incremental (delta) load?
Design cases around every way a delta can behave, not just new rows. Inserts: a new source row appears in the target exactly once. Updates: the changed row is updated — or versioned, if SCD2 — and no other row is touched. Deletes: know the spec — hard delete, soft-delete flag, or ignored — and test the chosen behavior explicitly. Unchanged rows: confirm they are not rewritten, which count checks will not reveal; compare audit or update timestamps. Boundary conditions: a record whose timestamp equals the watermark exactly — an off-by-one comparison (> versus >=) either drops it or double-processes it. Rerun: execute the same window twice and verify the target is unchanged — idempotency tested from the QA seat. Late-arriving data: a record with an old event timestamp arriving after its window closed. For each case, seed the source deliberately in a test environment — waiting for production data to cover these paths is not a strategy.
MediumAs a tester, how do you verify an SCD Type 2 dimension load?
Use structural queries, not eyeballing. One current version per key: group by business key and assert the count of current-flagged rows is exactly one — this catches both duplicated and missing current rows. No overlapping or gapped history: with LAG, compare each row's effective start against the previous row's effective end per key; overlaps double-count when facts join the dimension, gaps drop rows. Change detection: update a tracked attribute in the source, run the load, and verify a new version was created, the old one was closed with the correct end date, and the current flag moved. Then update a non-tracked attribute and verify no new version appears — over-triggering silently explodes the dimension. Finally, rerun the same load and confirm version counts are stable. All five checks fit in reusable SQL and belong in every regression run of a dimension load.
MediumHow do you classify ETL defects, and why does the taxonomy matter?
Classify along the axis of what has to change to fix it. Source data defects: the pipeline behaved correctly on bad input — duplicates, invalid dates, broken encodings upstream; the fix sits with the data owner, and the pipeline question is whether it should have rejected or quarantined the row. Mapping or spec defects: the STM is wrong, ambiguous, or contradicts source reality — the code faithfully implements a wrong rule. Code defects: output disagrees with an unambiguous STM. Environment or configuration defects: wrong connection, partial file pickup, jobs run out of sequence, permissions. Plus performance defects: correct output, unacceptable load window. The classification matters practically: it routes the fix to the right owner, prevents developers "fixing" code to match bad data, and trend analysis over categories shows where quality effort should go — a project drowning in spec defects has a requirements problem, not a coding problem.
HardA transformation is being changed. How do you regression-test the pipeline without reloading everything?
The goal is proving the change altered only what it was meant to alter. Impact analysis first: from the changed mapping or code, list affected target tables and columns; regression scope is those plus everything downstream of them. Then a baseline diff: run the old and new logic against the same frozen input in a test environment and compare outputs — full EXCEPT on modest volumes, column aggregates and row-hash comparisons at scale. Every difference must be explainable by the change request; unexplained diffs are defects. Alongside that, keep a standing suite of assertion queries — counts, duplicates, referential integrity, SCD structure, key business aggregates — versioned and executed on every release, so the checks that caught last year's defects keep running. Snapshot key aggregates before the production deployment as a rollback reference. The trap to name explicitly: regression-testing only the changed table and missing fan-out effects downstream.
HardThe table has 500 million rows and row-by-row comparison is infeasible. How do you reconcile source and target?
Tier the comparison so expensive checks run only where cheap ones fail. Tier one: row counts per partition — load date, region, source system — which localizes any discrepancy immediately. Tier two: column-level profiles compared source versus target — SUM and MIN/MAX on numerics, COUNT(DISTINCT) on keys, null counts per column, length profiles on strings. These are single-pass aggregations even at 500 million rows, and a mismatch tells you which column and partition to chase. Tier three: hashed buckets — compute a row hash, bucket rows by key (for example MOD of a key hash into 1,024 buckets), aggregate hashes per bucket on each side, and run row-level EXCEPT only on mismatched buckets, shrinking the row-by-row work by orders of magnitude. Optionally add stratified samples with full-column comparison for content confidence. Two cautions: make hashing deterministic across engines by casting and formatting consistently first, and reconcile against a consistent snapshot, or in-flight loads generate false diffs.
HardHow do you build and maintain test data for ETL testing?
Two sources, for different jobs. Masked production subsets give realistic distributions, volumes, and the messiness synthetic generators miss — but subsetting must be referentially consistent: pull the parent rows for every child you sample, or you manufacture fake orphan defects. Masking must happen before data reaches the test environment and must preserve the properties tests depend on — formats, key uniqueness, joinability — or half the suite breaks. Synthetic data covers what production does not have yet: NULLs in every nullable column, max-length strings, boundary dates, invalid values the reject path should catch, duplicate keys, a record timestamped exactly at the load watermark. Keep synthetic cases as versioned files with worked expected outputs so they double as regression fixtures. Refresh cadence matters: stale test data drifts from production schema and distributions, and the suite quietly stops testing reality. The interview-worthy line: production copies find unknown defects; synthetic data proves known risks are handled.
HardIf you were to automate ETL testing, what would the framework need?
Five things. Assertions as code: every check — counts, duplicates, referential integrity, transformation recomputes, SCD structure — is a versioned SQL query with a machine-readable pass condition, not a spreadsheet someone runs by hand. An execution harness: commercial tools in the QuerySurge mould specialize in scheduled cross-database comparison; a lightweight equivalent is a pytest- or dbt-test-style runner that executes queries against both systems and asserts on results. Tolerances and severity: some checks hard-fail the pipeline (duplicate keys), others warn within a threshold (a row count within a small tolerance for a snapshot source) — encoding that judgment is most of the design work. Integration: run in CI on every code change and post-load in the scheduled pipeline, so regression and production monitoring share one suite. History: persist results per run, because a metric drifting toward its threshold is a defect signal no single run shows. Tools vary; these requirements do not.
Related Guides
Keep Preparing
Move between roadmaps, interview questions, and tools without losing your preparation thread.
Is ETL testing still a good career in 2026 with ELT and dbt?
The work is shifting shape, not disappearing. As transformation moves into the warehouse, validation becomes SQL-first and increasingly automated, and pure manual-execution roles are shrinking. But demand for people who can design data validation — at services companies, GCCs running large migration programs, and product teams building pipelines — remains real. The strongest position is ETL testing skill plus automation: assertion suites running in CI, not spreadsheets of manually run queries. Migration and modernization projects in particular hire heavily for this.
How much SQL do I need for an ETL testing interview?
More than most candidates expect. You should write, without references: multi-table joins including the LEFT JOIN orphan pattern, GROUP BY with HAVING for duplicates, set operators (MINUS/EXCEPT) with their direction and duplicate caveats, aggregate profiling with SUM, COUNT DISTINCT and null counts, and window functions — ROW_NUMBER for duplicate inspection, LAG for SCD date-range checks. NULL semantics come up constantly. Expect at least one live query round; describing checks verbally without writing them usually is not enough.
Do I need experience with a specific ETL testing tool?
Rarely as a hard requirement. Job posts list tools, but interviews test transferable method: what to check, in what order, and the SQL that does it. If you know a commercial comparison tool in the QuerySurge mould, or have built a homegrown SQL harness, present it as automation of checks you can also do manually. A candidate who writes clean validation SQL but has not used the team's specific tool beats one who knows the tool's menus but cannot write the orphan check underneath.
How is ETL testing different from database testing?
Database testing validates one system: schema, constraints, stored procedures, CRUD behavior, transactions. ETL testing validates movement and transformation between systems: did every source row arrive, were the mapping rules applied correctly, do keys still resolve, did types and precision survive the move. The test oracle differs too — database tests check behavior against a functional spec; ETL tests check target data against source data plus mapping rules. ETL testing also carries volume and cross-engine comparison problems that single-database testing never meets.
What is expected from freshers versus experienced candidates?
Freshers are tested on fundamentals: the core check types, clean SQL for each, NULL handling, and the ability to read a mapping document. At 2-6 years, interviewers add judgment: real defect stories with correct classification, delta-load and SCD2 test design, regression strategy for changes, reconciliation at scale, and automation experience. Experienced candidates who answer with fresher-level material — definitions and check lists without war stories or scale thinking — get marked down hardest, because the gap between resume and depth is obvious.
Next Step
Turn The Guide Into Practice
Use PrepNPlaced tools to turn this learning path into resume proof, targeted practice, and interview-ready explanations.