CoreTrail

Interview patterns

Recognize recurring problems and choose a reliable approach.

Chapter overviewPostgreSQL8 min read
On this page

Recognize a problem, then compose a solution

Interview questions often combine a few operations across different grains. The wording map suggests a starting point; the worked lessons show why the stages are needed and where a plausible shortcut breaks.

Suggested route: Try a pattern with a tiny fixture, then change the population or tie rule. Use mixed practice when you can identify a technique without its label.

By the end: Describe the sequence of transformations and reject an alternative with a concrete counterexample.

Wording → first technique

Interview wording First technique to consider
latest / earliest row ROW_NUMBER or PostgreSQL DISTINCT ON
exactly top N rows per group ROW_NUMBER
top N distinct values / levels DENSE_RANK
previous / next observed value LAG / LEAD
month-over-month / period change aggregate → LAG
percentage of total aggregate → SUM(...) OVER ()
at least one related row EXISTS
never / no matching row NOT EXISTS
every required item double NOT EXISTS or HAVING COUNT(DISTINCT ...)
both/all requested categories conditional aggregation / HAVING
consecutive dates deduplicate → row-number island key
new session after gap LAG → boundary flag → cumulative SUM
state/run changes LAG → changed flag → cumulative SUM
missing dates / zero-activity periods calendar spine → LEFT JOIN
first event then later event first-event CTE → join/existence after timestamp
ordered funnel stage timestamps / ordered existence checks
median / p95 / p99 PERCENTILE_CONT ... WITHIN GROUP
actual observed percentile value PERCENTILE_DISC ... WITHIN GROUP
bucket users into quartiles/deciles NTILE
relative rank of each row PERCENT_RANK / CUME_DIST
pivot categories to columns conditional aggregation
overlapping intervals self join + overlap condition
all entity × period combinations CROSS JOIN + LEFT JOIN

High-value composition patterns

Aggregate → window

Use whenever a comparison should happen after reducing data to the reporting grain.

Examples: MoM revenue, rank stores by total visits, percentage of total, cumulative monthly sales.

LAG → arithmetic

current metric
- previous metric
= absolute change
(current - previous) / previous
= percentage change

Protect a zero previous value with NULLIF.

LAG → flag → cumulative SUM

Use for sessions, state changes, event runs, and many gaps-and-islands problems.

ROW_NUMBER → filter

  1. Partition by business key
  2. Order by preferred survivor
  3. Assign ROW_NUMBER
  4. Keep rn = 1

Use for latest records and deterministic deduplication.

Calendar → LEFT JOIN

  1. Generate expected dates
  2. Aggregate observed data
  3. LEFT JOIN on the date
  4. Fill zero only when appropriate

Needed when “no row” must appear explicitly as a date with zero activity.

CROSS JOIN → LEFT JOIN

Use for students × subjects, stores × days, customers × months.

First event → later event

  1. MIN(event_time) per entity
  2. Establish first-event attributes
  3. Find events after first_time

Useful for first purchase, repeat purchase, activation, campaign follow-up, and retention questions.

Percentile decision map

Question Use
“What is the p95 threshold?” PERCENTILE_CONT(0.95) WITHIN GROUP
“Give an actual observed value at the percentile” PERCENTILE_DISC
“Where does each row rank from 0–1?” PERCENT_RANK()
“What fraction is at or below this row?” CUME_DIST()
“Split rows into 10 groups” NTILE(10)

Output-grain checks

Before writing the query, state:

  1. What does one input row represent?
  2. What should one output row represent?
  3. Are duplicates meaningful?
  4. Can dates/periods be absent?
  5. How should ties be handled?
  6. Does “previous” mean previous row or previous calendar period?
  7. What population belongs in the denominator?

These decisions usually determine the correct SQL pattern before syntax does.

In this chapter

How to study

Read the wording column and try to name the technique before looking right. In an interview, write the output grain and edge case before writing syntax.

Type a concept, keyword, or function.