Self-Assessment Quiz: SQL Transformations
Twenty questions. Aim for 16 or more. This is the most transferable chapter in the book; treat 18 as the bar.
Question 1
Which is NOT a tell that you are thinking procedurally?
- A. A loop over query results issuing more queries
- B. A correlated subquery in the SELECT list
- C. A self-join comparing a row to its neighbor
- D. A CTE with several named steps
Question 2
A window function differs from GROUP BY in that it:
- A. Is faster
- B. Computes across related rows without collapsing them
- C. Cannot be filtered
- D. Requires an index
Question 3
For deduplication you must use:
- A.
RANK() - B.
DENSE_RANK() - C.
ROW_NUMBER() - D.
NTILE(1)
Question 4
Why?
- A. It is faster
- B.
RANKgives tied rows the same number, soWHERE rank = 1keeps all of them - C.
RANKcannot be used withPARTITION BY - D.
ROW_NUMBERhandles nulls better
Question 5
With an ORDER BY and no explicit frame, the default frame is:
- A. The whole partition
- B.
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW— a running aggregate - C.
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW - D.
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
Question 6
RANGE BETWEEN 2 PRECEDING AND CURRENT ROW differs from ROWS in that it:
- A. Is faster
- B. Includes all rows whose ORDER BY value is within range, including peers
- C. Only works with numeric columns
- D. Ignores the partition
Question 7
LAST_VALUE under the default frame returns:
- A. The last row of the partition
- B. The last row of the current peer group — the current row itself when the ordering is unique
- C. NULL
- D. The first row
Question 8
"CTEs are optimization barriers" is:
- A. True in all engines
- B. True in PostgreSQL before version 12, and repeated as a general fact
- C. Never true
- D. True only for recursive CTEs
Question 9
A recursive CTE must use UNION ALL rather than UNION because:
- A.
UNIONis not supported - B.
UNIONdeduplicates every iteration — slow, and it masks a cycle - C.
UNION ALLis required by the standard - D.
UNIONcannot reference the CTE
Question 10
A depth guard in a recursive CTE:
- A. Improves performance
- B. Converts an infinite loop into a wrong answer you can detect
- C. Is required syntax
- D. Prevents duplicates
Question 11
Prefer a flattened dimension over recursion when:
- A. The hierarchy is large
- B. The depth is bounded and known
- C. The engine lacks
WITH RECURSIVE - D. Never
Question 12
The constraint on pivoting in SQL is:
- A. It requires a specific engine
- B. You must know the columns in advance, so a dynamic pivot generates SQL
- C. It cannot aggregate
- D. It loses null rows
Question 13
Which deduplication pattern silently composes rows that never existed?
- A.
ROW_NUMBERwith a tiebreaker - B.
DISTINCT ON - C.
GROUP BYwithMAX()per column - D.
DISTINCT *
Question 14
Why is the tiebreaker in ROW_NUMBER() OVER (... ORDER BY ts DESC) not optional?
- A. It improves performance
- B. Without it, deduplication is non-deterministic and re-runs produce different results
- C. The engine requires two ORDER BY columns
- D. It prevents nulls
Question 15
After a deduplication you should assert:
- A. That rows equal distinct keys
- B. That no keys were dropped
- C. Both — a dedup fails in two directions
- D. Neither; the query is deterministic
Question 16
The general gaps-and-islands technique is:
- A. Sort and compare adjacent rows
- B. Create a group identifier constant within an island, then group by it
- C. Use a recursive CTE
- D. Self-join on offset
Question 17
The general form of that technique is:
- A.
date - row_number - B. Flag the breaks, then take a running sum of the flag
- C.
DENSE_RANKover the ordering - D.
NTILEon the gap size
Question 18
A backward-looking window function at a batch boundary produces:
- A. An error
- B. Missing rows
- C. Artifacts — an excess of short sessions at each window start, which looks like real behavior
- D. Duplicates
Question 19
The fix is:
- A. A larger batch
- B. Overlap the input and emit only records whose start falls in the target window
- C. Sort differently
- D. Disable the window function
Question 20
Before checking join strategy and estimates in a transformation's plan, look for:
- A. Index usage
- B. Sorts you did not ask for — window functions with different partitionings force one each
- C. Parallelism
- D. Buffer hits
Answer Key
1. D — §18.1. A CTE with named steps is a readability practice, not a procedural tell.
2. B — §18.2. That clause is the whole difference.
3. C — §18.2.
4. B — §18.2. Which is exactly the bug that produces duplicates in a deduplication step.
5. B — §18.3. So adding an ORDER BY silently turns a total into a running total.
6. B — §18.3. Two rows on the same date show the same running total.
7. B — §18.3, ⚠️ callout. Under RANGE, CURRENT ROW means the last peer of the current row —
the same peer rule as Question 6. With a unique ordering that is the current row, which is the form
the surprise is usually reported in. A is the answer people expect; the default frame ends at the
current row, not at the partition's end.
8. B — §18.4. Modern engines inline and decide.
9. B — §18.5. And masking a cycle is worse than surfacing it.
10. B — §18.5. Strictly better than running forever.
11. B — §18.5. Simpler, faster, and easier for analysts. Recursion earns its complexity when depth is genuinely variable.
12. B — §18.6. And a new value silently adds a column, which is a schema change every run.
13. C — §18.7. MAX(quantity) is the maximum across versions, not the quantity from the latest
one. If the columns are not independent — and they are not — you get a row that never existed.
14. B — §18.7. Which breaks reproducibility in a way that is very hard to diagnose.
15. C — §18.7, 🔎 callout.
16. B — §18.8.
17. B — §18.8. date - row_number is a special case of it.
18. C — §18.9, ⚠️ callout. Which is why it survives.
19. B — §18.9. Chapter 13 §13.4's overlap window applied to a transformation, needing the same idempotent write.
20. B — §18.10. Consolidating them is frequently a large free win and is invisible unless you read the plan.
Topic map
| Missed | Reread |
|---|---|
| 1 | §18.1 — set-based thinking |
| 2, 3, 4 | §18.2 — window functions |
| 5, 6, 7 | §18.3 — the frame clause |
| 8 | §18.4 — CTEs |
| 9, 10, 11 | §18.5 — recursion |
| 12 | §18.6 — pivoting |
| 13, 14, 15 | §18.7 — deduplication |
| 16, 17 | §18.8 — gaps and islands |
| 18, 19 | §18.9 — sessionization |
| 20 | §18.10 — reading the plan |