188 Data Scientist Interview Questions & Answers

92 top • 12 Amazon • 15 Apple • 13 Google • 12 Meta • 15 Microsoft • 15 Netflix • 14 NVIDIA

Data Scientist icon

Questions with Detailed ExplanationsWith Detailed Explanations

(Last Updated: September 8, 2026)

61. How do ETL and ELT differ?Data EngineeringEasy

Question Details

A source emits raw customer events and the destination is an analytical lakehouse or warehouse. Compare transforming before load with loading immutable raw data before transformation. Address freshness, schema and PII validation, compute location, lineage, replay and backfill, cost, security, and consumer isolation. State the source and curated contracts and how each approach recovers from a partially failed transformation.

Short Interview Answer (30-60 seconds)

ETL transforms before loading curated data, while ELT loads immutable raw data first and transforms it inside the lakehouse or warehouse. ETL favors earlier validation and PII removal. ELT favors easier replay, backfills, schema evolution, and reuse of raw data.

Detailed Explanation

The question asks when customer information should be cleaned and changed before people use it for reports or analysis. One design changes the information first and stores only the finished result. The other stores the original information safely first and changes it later. You should compare how quickly results arrive, where the work happens, what is stored, how private information is protected, how much each design can cost, how people are kept away from unfinished data, and what happens if part of the work fails. You should also explain the rules for the original and finished information.

Useful Questions to Ask the Interviewer
  1. Is the destination mainly a lakehouse, a warehouse, or a platform that supports both raw and curated storage?
  2. What freshness target do consumers need: batch delivery in minutes or hours, or near-real-time delivery?
  3. Are we allowed to retain raw PII, and what encryption, access-control, masking, and retention rules apply?
  4. Must historical data be replayable when transformation logic or the source schema changes?
  5. Should consumers have access only to curated data, or may restricted engineering users also access the raw layer?
How do ETL and ELT differ? diagram
How to Explain It in an Interview

Start with the practical difference. ETL means Extract, Transform, Load. The pipeline ingests source events, transforms and validates them in staging or pipeline compute, and then loads curated data into the analytical lakehouse or warehouse. ELT means Extract, Load, Transform. The pipeline first stores an immutable raw copy, then performs the main transformations using compute inside the warehouse or lakehouse.

In the diagram, the source contract represents customer events serialized as JSON and delivered through HTTPS or Kafka. Required fields include event_id, customer_id, event_type, event_time, and payload. event_time is an ISO 8601 UTC event timestamp. Producer ordering is best effort, duplicate events are possible, and the source schema is versioned so it can evolve.

For ETL, ingestion performs schema validation, identifies PII patterns, and applies basic quality checks. The staging transformation layer then cleans and validates the events, conforms types, applies business rules, enriches data when necessary, deduplicates records, and handles PII before curated data is loaded. The transformation compute is outside the analytical warehouse in the ETL pipeline or staging environment.

The main ETL benefit is early control. Invalid data or sensitive fields can be rejected, removed, masked, or transformed before the curated analytical store is written. Because only curated data may be retained in the destination, storage can be lower and the PII blast radius can be smaller. Consumers receive curated-only access by default.

The ETL tradeoff is replay. If the transformation logic changes, rebuilding history is harder when the raw input was not retained. Recovery may require replaying the source or reading retained staging snapshots. For a partially failed ETL transformation, fix the transformation logic, identify the affected window, restart from a valid checkpoint or retained staging input, and perform idempotent writes to the target curated partitions. Then rerun quality checks and verify lineage before making the corrected data available.

For ELT, ingestion first appends the source events to an immutable raw landing layer. The raw layer keeps the original columns and is not updated or deleted as part of normal transformation processing. It can be partitioned by event_date and stored in analytical formats such as Parquet or JSON according to the platform design. The main transformations then run inside the warehouse or lakehouse using its compute engine, for example SQL, dbt, or Spark where those technologies are available.

The ELT transformation cleans, validates, enriches, deduplicates, and handles PII, then writes curated tables or views. Transformation output should be deterministic and idempotent so retrying the same input produces the same logical curated result instead of creating duplicates.

ELT makes replay and backfill easier because the immutable raw input remains available. If a transformation fails, fix the SQL or transformation logic, identify the failed raw partitions or event-time range, rerun only that input, and overwrite or safely merge the affected curated partitions. Then verify quality checks and lineage. The raw data does not need to be recovered from the producer because it was already retained.

Freshness depends on the implementation rather than the acronym alone. In the diagram, ETL commonly delivers batch freshness in minutes to hours, although streaming ETL is possible and can be more complex. ELT can support near-real-time to minute-level freshness when ingestion, transformation frequency, and warehouse or lakehouse capacity support it. Neither pattern automatically guarantees a particular latency.

The curated contract should be consistent for consumers regardless of whether ETL or ELT produced it. In the diagram, the curated grain is one row per logical event identified by customer_id, event_type, event_time, and event_id. The schema uses stable typed columns with surrogate keys where appropriate. Data is partitioned by event_date in UTC, event_id is deduplicated, PII is handled according to policy, and the target freshness SLA is under 15 minutes for the illustrated design. Consumers receive read-only access through governed tables or views, with row-level or column-level security where needed.

Quality checks apply to both approaches. They include schema validation, completeness checks such as null and range checks, uniqueness of event_id, timeliness or late-data thresholds, referential checks where applicable, and PII scans or masking. These checks help prevent silent loss, duplication, invalid records, or sensitive-data leakage.

Lineage should record the path from the source to the final curated datasets and consumers. ETL typically records source to staging to curated. ELT records source to raw to curated. Keeping raw lineage in ELT is especially useful when rebuilding data after transformation changes.

Security differs mainly in when sensitive raw data is retained. ETL can remove or mask PII before it reaches the analytical destination. ELT may store PII in the raw layer, so raw storage requires encryption, strict access controls, auditing, masking or tokenization where appropriate, and retention policies. Raw and curated areas should be isolated, and ordinary BI or data-science consumers should normally receive access only to curated data.

Cost also moves to different places. ETL may use more external pipeline compute but can store less raw data. ELT stores more data because it keeps the raw copy and uses warehouse or lakehouse compute for transformations. In return, ELT can reduce the operational effort needed to replay historical data, backfill changed logic, or support new downstream use cases.

The practical choice depends on requirements. Choose ETL when early validation or PII removal is especially important and storing raw data in the analytical destination is undesirable. Choose ELT when immutable raw retention, replayability, backfills, schema changes, lineage, and flexible reuse are priorities. Both patterns should expose the same trusted curated contract to consumers, isolate incomplete or raw data, track lineage, run quality checks, and recover with deterministic idempotent writes.

Technical Approach
  1. Define the source contract: JSON event structure, required fields, event-time semantics, schema version, best-effort producer ordering, duplicate behavior, and PII fields.
  2. Define the curated contract that consumers should receive regardless of ETL or ELT, including grain, typed schema, partitioning, deduplication rule, freshness target, PII policy, and access controls.
  3. For ETL, ingest the events, validate schema and PII, transform in staging or ETL compute, then load only curated data into the analytical destination.
  4. For ELT, ingest and append immutable raw data first, then transform it using warehouse or lakehouse compute into the curated layer.
  5. Deduplicate deterministically by event_id and make curated writes idempotent so retries do not duplicate logical events.
  6. Track lineage from source through staging or raw storage to curated datasets and consumers.
  7. Run schema, completeness, uniqueness, timeliness, referential, and PII checks where applicable.
  8. Isolate consumers from raw, staging, and partially completed outputs; expose governed curated tables or views.
  9. On an ETL failure, restart the affected window from the source, checkpoint, or retained staging snapshot and safely rewrite the affected curated partitions.
  10. On an ELT failure, rerun the affected immutable raw partitions and safely overwrite or merge the corresponding curated partitions.
  11. Compare freshness, compute location, storage cost, transformation cost, replayability, security, schema volatility, and operational complexity before choosing the pattern.
Practical Insights

ETL usually spends more transformation compute before data reaches the warehouse or lakehouse and may store less raw data there. Historical replay can require more operational work if the source or staging input was not retained. ELT stores an extra immutable raw copy and uses analytical-platform compute for transformations, so raw-storage and warehouse or lakehouse compute costs can be higher. In exchange, replay and backfill are usually simpler because the original input is already stored. Both approaches also require ongoing work for orchestration, data-quality checks, lineage, monitoring, security, retention, retries, and maintenance of idempotent transformation logic.

Why Interviewers Ask This

This question tests whether the candidate understands the operational difference between transforming before load and loading raw data before transformation. The interviewer is looking for judgment about freshness, schema and PII validation, compute location, lineage, replay and backfill, cost, security, consumer isolation, data contracts, and deterministic recovery after a partial transformation failure.

Common interview mistakes

A common mistake is saying ETL is always batch and ELT is always real time. Either pattern can use batch or streaming components, and freshness depends on the implementation. Another mistake is assuming ELT performs no validation during ingestion; basic contract and security checks can still happen before raw data is accepted. Candidates also forget that retained raw PII requires stronger controls, or that ETL replay becomes difficult if neither the source nor staging input can be replayed. Another mistake is treating retries as simple appends. Reprocessing must use deterministic deduplication and idempotent writes so it does not create duplicate curated results. Finally, consumers should not see raw, staging, or partially transformed data merely because the pipeline is still processing.

Interview tip

Lead with the order difference, then immediately explain why it matters. ETL transforms before loading curated data; ELT preserves immutable raw data first and transforms it inside the analytical platform. Compare freshness, schema and PII handling, compute location, lineage, replay, cost, security, consumer isolation, and partial-failure recovery. Finish by explaining that neither pattern is universally better and that safe retries require retained input plus idempotent curated writes.

Interviewer may ask next
How would you recover if an ELT transformation fails halfway through processing a day's customer events?

Keep the immutable raw input unchanged and prevent consumers from using the incomplete curated result. Fix the transformation logic, identify the affected raw partition or event-time range, and rerun only that input. Write the curated output idempotently by safely overwriting the affected target partition or merging on the stable event identifier so the rerun does not duplicate events. Then rerun schema, completeness, uniqueness, timeliness, referential, and PII checks as applicable, verify lineage, and expose the corrected curated data.

When would you choose ETL instead of ELT even if the warehouse has powerful transformation compute?

I would favor ETL when sensitive raw fields should not be retained in the analytical platform, when governance requires PII to be masked or removed earlier, or when the organization intentionally wants to store mainly curated data. I would still retain a controlled replay source, checkpoint, or staging snapshot when policy allows it. Otherwise, transformation changes and backfills may require rereading the operational source. The choice is therefore driven by governance, replay, cost, freshness, and operational requirements rather than compute capability alone.

62. Design a daily pipeline that loads orders from a production database into a warehouse.Data EngineeringMedium

Question Details

Define the source order and order-item keys, update semantics, deletion handling, extraction method, source-load limits, and daily freshness target. Design raw landing, incremental watermarks or change capture, staged transformations, warehouse fact and dimension grains, deduplication, reconciliation and quality gates, orchestration, lineage, atomic publication, alerts, retries, and a two-year backfill path that does not duplicate orders or expose partial tables.

Short Interview Answer (30-60 seconds)

I would extract only incremental order changes, land them in replayable raw storage, validate and reconcile them, deduplicate by source key and change order, then perform idempotent warehouse upserts. I would publish atomically, checkpoint only after success, alert on failures or freshness, and reuse the same logic for two-year backfills.

Detailed Explanation

The goal is to copy complete and correct order information from the live business database into an analytics database once each day. I first need to know how each order and item is identified, how changes and removals appear, how much work the live system can safely handle, and when the daily result must be ready. The design must also recover safely after a failure, check that nothing was lost or repeated, keep a record of where the information came from, and reload two years of older information without creating duplicates or showing unfinished results.

Useful Questions to Ask the Interviewer
  1. What are the exact primary keys for orders and order_items? Is an item identified by order_item_id, or by a composite key such as order_id plus a line number?
  2. Does the production database support CDC, or should extraction use a reliable updated_at watermark?
  3. If a watermark is used, how are hard deletes exposed to the pipeline?
  4. Are deletes represented as an is_deleted soft-delete flag, hard-delete events, or both, and should deleted records remain in the warehouse?
  5. Can extraction read from a replica, and what batch-size, concurrency, lag, or load limits should protect the production database?
  6. What is the agreed T+1 freshness deadline?
  7. What reconciliation controls are available, such as source change counts or control totals?
  8. Should the warehouse expose only current order state, or is additional historical versioning required?
Design a daily pipeline that loads orders from a production database into a warehouse. diagram
How to Explain It in an Interview

I would organize the design as the same five stages shown in the diagram.

1. Production database and source contract

Assume orders uses order_id as its primary key. Assume order_items uses order_item_id as its primary key and order_id as a foreign key. If the actual source uses a composite order-item key, I preserve that exact source key instead. The pipeline must not invent a different identity because deduplication, deletion handling, and warehouse upserts depend on the true source business key.

The source can contain inserts and updates. Deletes may be represented by a soft-delete flag or as a hard-delete event. I define the deletion contract explicitly so the same rule is used during daily loads, retries, and backfills.

2. Incremental extraction

I prefer CDC, or change data capture, when the source supports it. CDC captures changes rather than scanning the entire source every day. For CDC, I store the source log position or CDC offset as the incremental checkpoint and resume from the last committed checkpoint after a retry.

If CDC is unavailable, I can use a reliable updated_at watermark. In that case I use a deterministic checkpoint such as (updated_at, primary_key) so multiple rows with the same timestamp are not skipped. A watermark by itself cannot detect a row that was physically deleted, so hard deletes require a separate deletion signal.

I protect production by reading from a replica when available, bounding batch size and concurrency, and backing off when source lag or load rises. I would not invent a fixed throughput limit; the limit should come from the production system's capacity and service requirements.

3. Immutable raw landing and validation

Every extracted change first lands in immutable raw storage. The raw layer is replayable: existing records are not silently rewritten when a job is retried. I partition it by ingestion date and retain the source operation, source key, source change position or watermark information, and ingestion timestamp.

Before transformation, I run schema validation, required-field checks, key checks, order-to-item relationship checks, and duplicate-key detection. Bad records go to a reject area instead of silently reaching the warehouse.

I also reconcile the extraction against the source change range using available row counts or control totals. A failed reconciliation or quality gate stops publication.

4. Transform and reconcile

The transformation step keeps three time concepts separate. A business timestamp describes when something happened in the source business process. A change timestamp or position describes the source change order. A load timestamp describes when the warehouse processed the data.

I deduplicate by the true source primary key. With CDC, I keep the newest record according to the source change position or version. With a timestamp-watermark design, I use the deterministic (updated_at, primary_key) ordering defined by the source contract.

Deletes follow one configured policy. For example, a delete event can set is_deleted = true, or it can physically remove the warehouse row if that is the required policy. The same policy must apply to daily processing and backfills.

For the warehouse write, I use an idempotent MERGE or equivalent upsert by source business key. For CDC data, an incoming change is applied only when its source change position or version is newer than the target's stored version. Reprocessing the same change therefore produces the same final state rather than duplicate rows. A watermark implementation uses its equivalent deterministic source ordering.

5. Warehouse grain and atomic publication

The order entity or dimension has one row per order_id. Representative fields are order_id, customer_id, status, total_amount, updated_at, and is_deleted.

The fact_order_item table has one row per source order-item key. Representative fields are order_item_id, order_id, product_id, quantity, price, updated_at, and is_deleted. If the source uses a composite item key, that composite key defines the fact grain instead.

After transformation and reconciliation pass, I publish the new warehouse state atomically using a mechanism supported by the chosen warehouse, such as a transactional publish or validated table/version swap. Consumers continue to see the previous complete state until the new state is successfully published. If publication fails, they never see half-updated tables.

Orchestration, checkpoints, retries, and alerts

A daily dependency DAG orchestrates extraction, validation, transformation, reconciliation, and publication.

The key recovery rule is that the committed incremental checkpoint advances only after successful publication. If a later stage fails, the next retry starts from the previous committed checkpoint and may safely process the same input again. Business-key plus source-order-aware writes make that retry idempotent.

I alert on extraction failures, quality failures, reconciliation mismatches, publication failures, and missed freshness targets.

Lineage and audit

For every run, I record the source system and table, source key, change position or watermark information, and load batch identifier. I maintain lineage from source change to raw data to staging to warehouse. Warehouse audit fields such as loaded_at and batch_id make a published record traceable to the pipeline run that produced it.

Daily freshness target

The target is the agreed T+1 deadline. I monitor the latest successfully published source change, not only whether the scheduler finished. If the newest successfully published change misses the freshness SLA, the pipeline raises an alert.

Two-year backfill

I divide the two-year history into bounded ranges so the backfill does not overload the source. Each range lands in the same immutable raw layer and runs through the same validation, reconciliation, deduplication, deletion handling, and idempotent warehouse-write logic as the daily path.

For CDC-backed data, version-aware MERGE logic prevents an older backfill change from replacing a newer warehouse row. Business-key matching prevents duplicate orders and order items. Each validated backfill range is published atomically, so consumers never see a partially loaded historical range.

Main tradeoff

CDC provides a natural change sequence and better delete capture, but it requires source support and additional operational management. An updated_at watermark is simpler, but it needs reliable timestamps, a deterministic tie-breaker, and a separate way to discover hard deletes. In both designs, the important guarantees come from replayable raw data, deterministic ordering, reconciliation, idempotent writes, safe checkpointing, and atomic publication rather than from transport semantics alone.

Technical Approach
  1. Confirm the exact order and order-item keys, update semantics, deletion representation, extraction capability, source-load limits, and T+1 deadline.
  2. Extract incrementally using CDC when available; otherwise use a reliable updated_at watermark with a deterministic primary-key tie-breaker and a separate hard-delete signal.
  3. Protect production with a replica when available, bounded batch size and concurrency, and backoff when source load or replica lag rises.
  4. Land every change in immutable raw storage partitioned by ingestion date, retaining the source operation, source key, source ordering information, and ingestion timestamp.
  5. Validate schema, required fields, keys, relationships, and duplicate keys; route invalid records to a reject area.
  6. Reconcile extracted counts or available control totals with the source change range, and block publication if the gate fails.
  7. Deduplicate by the true source key using the source's deterministic change order.
  8. Apply the configured deletion policy and perform an idempotent, source-order-aware MERGE or equivalent upsert by business key.
  9. Validate the transformed result and publish the warehouse state atomically.
  10. Advance the committed checkpoint only after successful publication; retry from the previous checkpoint after failure.
  11. Record run-to-source-to-target lineage and alert on extraction, quality, reconciliation, publication, or freshness failures.
  12. Process the two-year backfill in bounded ranges through the same raw, validation, reconciliation, deduplication, deletion, idempotent write, and atomic-publication path.
Practical Insights

A normal daily run should do work mainly for rows that changed, rather than repeatedly scanning every historical order. If C rows changed that day, extraction, validation, and transformation are roughly proportional to C, plus the warehouse cost of matching those keys during the upsert. Raw-storage usage grows with the number of retained changes because the raw layer is replayable. CDC adds operational complexity but gives a stronger change sequence and better delete capture. A watermark is simpler but needs careful tie-breaking and delete handling. The main maintenance costs are schema changes, source protection, reconciliation rules, lineage, alerts, retention, and keeping backfills compatible with daily idempotency rules.

Why Interviewers Ask This

This question tests whether the candidate can design a reliable production data pipeline rather than simply copy rows. The interviewer is looking for judgment about source impact, source and warehouse grain, incremental extraction, updates and deletes, checkpoints, deterministic deduplication, reconciliation, quality gates, idempotent writes, retries, lineage, freshness, atomic publication, and safe backfills. A strong candidate should explain failure behavior clearly: checkpoints must not move past unpublished data, retries must not duplicate rows, older historical changes must not replace newer warehouse state, and consumers must not see a partially published load.

Common interview mistakes

Common mistakes are scanning the full production tables every day; inventing fixed source limits instead of agreeing them with the source owner; using only updated_at without a deterministic tie-breaker; assuming a watermark detects hard deletes; changing the source business key or warehouse grain; deduplicating by load date instead of deterministic source order; advancing the checkpoint before publication succeeds; claiming exactly-once business outcomes from transport delivery alone; allowing an old backfill change to overwrite newer warehouse state; skipping source-to-landing reconciliation; publishing related tables separately so consumers see partial results; using different deletion rules for daily loads and backfills; and checking only scheduler completion instead of the freshness of the latest successfully published source change.

Interview tip

Present the design from left to right: source contract, incremental extraction, immutable raw landing, validation and reconciliation, deterministic idempotent upsert, and atomic publication. Spend extra time on failure behavior. Explain exactly when the checkpoint advances, why retries do not duplicate data, how deletes are handled, and how the two-year backfill avoids both duplicate rows and stale overwrites.

Interviewer may ask next
How would you change the design if CDC is unavailable and you only have an updated_at column?

I would use a deterministic watermark such as (updated_at, primary_key). The timestamp identifies the change time and the primary key breaks ties when several rows have the same timestamp. I would persist that checkpoint only after successful atomic publication. If I intentionally reread a small overlap window, the business-key upsert and deterministic source ordering remove duplicates. The important limitation is hard deletes: a timestamp query cannot find a row after it has been physically removed, so I would require a soft-delete flag, deletion feed, tombstone table, or another explicit reconciliation mechanism. Source protection, raw landing, validation, retries, lineage, and atomic publication stay the same.

How do you backfill two years of orders while daily loads continue without duplicating data or overwriting newer rows?

I would divide the two-year history into bounded ranges and land every range in the immutable raw layer. The backfill uses the same source business keys, quality checks, reconciliation, deduplication, deletion policy, and source-order-aware upsert logic as the daily pipeline. With CDC-backed history, the target accepts an incoming row only if its source change position or version is newer than the target's stored version, so an older historical change cannot replace newer daily state. Business-key matching prevents duplicates. Each validated range is published atomically, and lineage records identify which source range and pipeline run produced each result.

63. How would you handle an upstream schema change?Data EngineeringMedium

Question Details

An event producer may add, remove, rename, or change the type, nullability, or meaning of a field. Define the current source and target contracts, compatibility policy, registry or validation point, raw preservation, and downstream lineage. Explain detection, classification, quarantine versus fail-open behavior, version migration, consumer communication, tests, backfill, and recovery when an unannounced breaking change has already entered storage.

Short Interview Answer (30-60 seconds)

I would detect and classify the new writer schema against explicit source and target contracts. Compatible, semantically safe changes can continue; breaking or ambiguous changes are quarantined. I would preserve raw data, use versioned mappings and contract tests, notify consumers, track lineage, and backfill affected data when needed.

Detailed Explanation

A producer may start sending information in a different shape, and that can break reports, models, or other systems that depend on it. I would first define what the producer sends today and what downstream users expect. Then I would detect changes as early as possible and decide whether each one is safe. Safe changes can continue. Unsafe or unclear changes should be isolated so they do not damage later data. I would also keep the original incoming records so I can repair historical data if a bad change has already been stored.

Useful Questions to Ask the Interviewer
  1. What are the current source and target contracts, including fields, types, nullability, meaning, and target grain?
  2. Which compatibility policy should be enforced: backward, forward, full, or one of the transitive variants?
  3. Where is schema validation performed, and do records carry a writer schema ID or version?
  4. For an incompatible change, should affected records be quarantined and unsafe downstream writes stopped?
  5. Is the original raw payload preserved so an affected range can be replayed or backfilled?
  6. Which downstream consumers need contract tests, communication, or coordinated migration?
How would you handle an upstream schema change? diagram
How to Explain It in an Interview

I would start with the current contracts. The source contract defines the producer's fields, types, nullability, and meaning. The target contract defines the schema and grain expected by downstream storage and consumers. I would also define the compatibility policy at the registry or validation point. Depending on upgrade requirements, that policy may be BACKWARD, FORWARD, FULL, BACKWARD_TRANSITIVE, FORWARD_TRANSITIVE, or FULL_TRANSITIVE.

Next, I would detect and classify the incoming change. Each record or batch should be associated with its writer schema ID or version so the pipeline knows which contract produced it. The validation point checks the new schema against the selected policy. Non-transitive policies compare compatibility with the latest relevant schema version, while transitive policies compare against prior versions as required by the policy. I would separately classify the business meaning of the change because structural compatibility does not prove semantic compatibility.

If the change is compatible and semantically safe, I would accept it, record the schema version, and continue. If it is breaking or ambiguous, I would send the affected records to quarantine, alert the owning team, and stop unsafe downstream writes. I would track schema-version drift, validation failures, and quarantined-record count so unexpected changes are detected quickly.

Before normalization, I would preserve the immutable raw payload together with its writer schema or schema version. This gives recovery a trustworthy source. I would write the normalized target only after validation. When migration is required, I would use an explicit versioned mapping only when the semantics are known. That can include a documented rename or alias, a compatible type conversion, a defined default, or introducing a new field. I would not silently guess how an incompatible value should be interpreted.

For rollout, I would propose the new contract, register it, and run producer and consumer contract tests. If required, I would support an old-and-new contract window while consumers migrate. I would then switch consumers to the new contract and retire the old contract only after a stability period. I would also record lineage from source schema version to transformation version to target and notify downstream owners before a breaking dependency is removed.

If an unannounced breaking change has already entered storage, I would first detect the affected range. Then I would reprocess from the preserved raw source, apply the corrected versioned mapping, and write the repaired target through an idempotent backfill so rerunning recovery does not create duplicate business results. Finally, I would verify the repair using record-count reconciliation and data-quality checks before closing the incident.

The main tradeoff is availability versus correctness. Allowing compatible, well-understood changes to continue reduces unnecessary pipeline outages. Quarantining breaking or ambiguous changes protects downstream correctness but delays those records. My default is therefore fail-open only for changes that satisfy the selected compatibility policy and have safe semantics, and fail-closed for changes that cannot be interpreted confidently.

Technical Approach
  1. Define the current source contract: fields, types, nullability, and meaning.
  2. Define the current target contract: expected schema and grain.
  3. Choose the compatibility policy and validation point.
  4. Detect the incoming writer schema ID or version and classify the change.
  5. If compatible and semantically safe, accept it, record the schema version, and continue.
  6. If breaking or ambiguous, quarantine affected records, alert the owner, and stop unsafe downstream writes.
  7. Preserve the immutable raw payload and writer schema or version before normalization.
  8. Use explicit versioned mappings only when rename, conversion, default, or new-field semantics are defined.
  9. Run producer and consumer contract tests, communicate the change, and migrate consumers safely.
  10. Record lineage from source schema version through transformation version to target.
  11. If a breaking change already landed, identify the affected range, reprocess from raw data, apply the corrected mapping, run an idempotent backfill, and reconcile counts and quality checks.
Practical Insights

The normal per-record cost is small: identify the writer schema, validate it, and apply the correct mapping. The bigger cost is operational. Supporting several contract versions adds tests, transformation rules, registry management, lineage, and consumer coordination. Preserving immutable raw data uses more storage, but it makes recovery much safer. Quarantine protects correctness but can delay data. Historical recovery can be expensive because the affected range must be read again, transformed, rewritten, and verified. Maintenance cost also grows if old contract versions remain supported for too long.

Why Interviewers Ask This

This question tests whether the candidate can evolve data contracts without silently corrupting downstream data. It evaluates judgment around source and target contracts, compatibility policies, schema validation, safe versus breaking changes, raw-data preservation, versioned migration, quarantine behavior, consumer communication, lineage, testing, backfills, and recovery after an unexpected change has already reached storage.

Common interview mistakes

Common mistakes include treating every schema change the same, assuming structural compatibility also means semantic compatibility, reading only the latest schema instead of identifying the writer schema, silently dropping unknown fields, using unsafe type casts, inventing defaults whose meaning is unclear, normalizing before preserving raw data, letting breaking records contaminate downstream storage, failing to quarantine ambiguous changes, omitting lineage between schema and transformation versions, skipping producer or consumer contract tests, retiring the old contract too early, and running a recovery backfill without idempotency or reconciliation.

Interview tip

Organize the answer around one decision: compatible and semantically safe changes continue; breaking or ambiguous changes are quarantined. Then explain contracts, validation, raw preservation, versioned migration, consumer rollout, lineage, and recovery. Explicitly cover what happens when the bad schema has already reached storage, because that demonstrates production-level judgment.

Interviewer may ask next
What would you do if a producer renamed a field without announcing it and records with the new schema were already stored?

I would first identify the affected schema version and time or data range, then stop unsafe downstream normalization for those records. I would confirm with the producer that the new field is truly a rename and not a different concept. After the semantics are confirmed, I would add an explicit versioned mapping, run producer and consumer contract tests, and record lineage from the source schema version through the corrected transform to the target. Then I would reprocess the preserved raw records through an idempotent backfill and reconcile record counts and data-quality checks before considering recovery complete.

When would you quarantine a schema change instead of allowing the pipeline to continue?

I would quarantine when the new schema violates the selected compatibility policy or when its meaning cannot be interpreted safely. Examples include an incompatible type change, removal of a field required by the target, a nullability change the target cannot accept, or a semantic change with no approved mapping. I would allow processing to continue only when the change is both structurally compatible under the chosen policy and semantically safe. Quarantine delays those records, but it prevents silent downstream corruption while the owner supplies a corrected contract or versioned migration.

64. How would you backfill 18 months of data without missing current production SLAs?Data EngineeringHard

Question Details

A partitioned daily pipeline has one canonical transformation path, limited shared compute, and downstream consumers that require today's data first. Define the backfill range, input and output versions, partition ownership, concurrency and throttling, checkpoints, idempotent writes, validation, isolation from current runs, and atomic promotion. Explain failure recovery, partial reruns, lineage, progress and cost monitoring, and how you prevent old backfill outputs or cache refreshes from racing with daily publication.

Short Interview Answer (30-60 seconds)

Give today's pipeline strict priority and let the backfill use only spare capacity. Pin versions, claim partitions, throttle concurrency, write idempotently to staging, validate, checkpoint, atomically promote, and retry only failed partitions while monitoring production SLA, backfill progress, throughput, resource use, and cost.

Detailed Explanation

The challenge is to rebuild 18 months of historical data without slowing the daily work that users need now. I would first define exactly which past days must be rebuilt and freeze the inputs and rules for that run. Today's work always goes first. Historical days use only spare capacity. Each day is owned by one worker at a time, written to a private staging area, checked before publication, and recorded after success. If one day fails, only that day is retried. Consumers continue to see the trusted production version until a validated replacement is published atomically.

Useful Questions to Ask the Interviewer
  1. What production SLA must today's daily partition meet?
  2. What shared compute limits or guardrails should cause the backfill to throttle or pause?
  3. Can the source data be read from a stable snapshot or version for the entire backfill?
  4. What validation checks are mandatory before replacing an existing historical partition?
  5. Does the destination support an atomic metadata or version switch for publication?
  6. Are downstream caches refreshed automatically, or must the pipeline explicitly refresh or invalidate them after publication?
How would you backfill 18 months of data without missing current production SLAs? diagram
How to Explain It in an Interview

I would begin with one rule: today comes first. The production run for partition T has the highest priority, and the backfill may process only historical partitions from T-18 months through T-1 day. Historical work consumes spare capacity and must throttle or pause whenever production SLA, lag, or shared-resource guardrails are threatened.

Before starting, I would create one immutable backfill manifest. It contains the historical range, a pinned input snapshot or version, a pinned transformation version, an output version, and a unique RUN ID. Pinning these values makes the run reproducible and gives clear lineage from source data to the final published result.

I would normally schedule the historical range oldest to newest. Before processing a partition, the orchestrator acquires a lease or claim for that date and RUN ID. Only one active owner can process the same partition for that run. This prevents duplicate workers and conflicting historical writes.

The daily production lane and historical backfill lane both execute the same canonical deterministic transformation. The key parameters are the partition date and the pinned versions from the manifest. Using one transformation path avoids having separate historical business logic that can drift from production behavior.

Backfill concurrency is bounded. I would make the cap configurable and adaptive rather than choosing an arbitrary fixed percentage. The scheduler can increase historical parallelism when production is comfortably within its guardrails, then reduce or pause backfill workers as production load rises.

Historical results do not write directly into the production-visible partition. Each result first goes to isolated staging identified by RUN ID and date partition. Writes must be idempotent: retrying the same RUN ID and partition must produce the same logical output, and already committed attempts must be recognized or safely replaced rather than duplicated.

After the staged write, I validate the partition. Checks can include row or count reconciliation, schema and contract checks, key, null, and range checks, and expected partition completeness. A failed validation does not change the currently published production version. That partition can be quarantined and retried independently.

After successful staging and validation, I record a checkpoint containing the partition, input version, output version, and status. Checkpoints allow recovery from the last successful point and make partial reruns possible without restarting the entire 18-month range.

Publication is a separate atomic step. The validated staged result is promoted only if the expected production generation or version is still current. If another writer has changed the target since the backfill started, the promotion aborts and the partition is revalidated or retried against the new state. This version precondition prevents stale historical work from overwriting a newer publication.

There is also a strict ownership boundary: the backfill may promote only partitions earlier than T, while the daily run owns T. That prevents historical jobs from racing with today's publication.

Any downstream cache refresh or invalidation happens only after the successful atomic commit and refers to the committed output version. No cache refresh should occur for an uncommitted staged result. This prevents stale or failed backfill output from becoming visible through caches before the actual data publication succeeds.

For recovery, a failure leaves the current production version unchanged. The orchestrator returns to the latest successful checkpoint and retries only the failed or unvalidated partition through the same canonical transformation path. This keeps failure recovery small and predictable.

I would monitor production SLA or lag, backfill throughput in partitions per hour, shared-resource utilization and guardrail usage, failure and retry rates, and completed, failed, and remaining partitions. I would also track compute-hours or equivalent spend. Lineage records the source partition/version, transformation version, RUN ID, and output version.

The main tradeoff is speed versus production safety. More historical concurrency finishes the backfill sooner but creates greater contention for limited shared compute. Less concurrency takes longer but gives production more headroom. The correct design makes backfill concurrency adaptive and always lets today's production workload win when capacity becomes constrained.

Technical Approach
  1. Define the backfill range as T-18 months through T-1 day.
  2. Create one immutable manifest containing the pinned input snapshot/version, transformation version, output version, and unique RUN ID.
  3. Give today's production partition T the highest scheduling priority.
  4. Allow historical work to use only spare shared compute with a bounded, adjustable concurrency cap.
  5. Throttle or pause backfill work whenever production SLA, lag, or resource guardrails are threatened.
  6. Process historical partitions in a controlled order, normally oldest to newest.
  7. Acquire a partition lease or claim so only one active worker owns a date for the RUN ID.
  8. Run both production and backfill through the same deterministic canonical transformation path.
  9. Write historical results idempotently to isolated staging identified by RUN ID and partition date.
  10. Validate row/count reconciliation, schema/contract, key/null/range rules, and expected partition completeness.
  11. Record a checkpoint after successful staging and validation with partition, input version, output version, and status.
  12. Atomically promote the validated staged result only if the expected production generation/version is still current.
  13. Allow the backfill to promote only partitions earlier than T; the daily run owns T.
  14. Refresh or invalidate downstream caches only after a successful commit and only for the committed output version.
  15. On failure, leave the production version unchanged and retry only the failed or unvalidated partition from the last successful checkpoint.
  16. Track lineage, production SLA/lag, backfill throughput, resource utilization, failures, remaining partitions, and compute cost until the manifest is complete.
Practical Insights

The total transformation work grows with the amount of historical data because every selected partition must be read and rebuilt. More concurrent workers can shorten elapsed time, but they also consume more shared compute and increase the risk of hurting today's SLA. Staging requires temporary extra storage because a new version exists before promotion. Checkpoints, leases, validation records, and lineage add small metadata costs but greatly reduce recovery work. The operational design is more complex than a simple bulk rerun, but it prevents a single failure or stale backfill attempt from forcing a full restart or corrupting production-visible data.

Why Interviewers Ask This

This question tests whether the candidate can execute a large historical rebuild without harming today's production workload. It evaluates workload prioritization under limited shared compute, reproducibility through pinned versions, safe partition ownership, bounded concurrency, throttling, idempotent retries, validation, checkpoints, atomic publication, race prevention, lineage, operational observability, cost awareness, and failure recovery. A strong answer separates processing from publication and explains how current production data remains authoritative while historical work progresses safely.

Common interview mistakes

Common mistakes include launching all 18 months at maximum concurrency, treating historical and today's runs as equal priority, using a separate transformation path for backfill, failing to pin the input or transformation version, letting multiple workers own the same partition, writing directly into production-visible storage, assuming retries are safe without idempotency, restarting all 18 months after one partition fails, publishing before validation, allowing the backfill to publish partition T, refreshing caches before the commit succeeds, and promoting without checking that the expected production version is still current. Another mistake is monitoring only backfill throughput while ignoring production SLA, shared-resource pressure, remaining work, retry rates, lineage, and cost.

Interview tip

Start with the rule "today first." Then explain the backfill plan, priority scheduling, bounded concurrency, partition ownership, canonical transformation, idempotent staging, validation, checkpointing, atomic promotion, and recovery. Make the two race-prevention rules explicit: backfill never owns T, and cache refresh happens only after a successful version-checked commit.

Interviewer may ask next
What would you do if the transformation logic changes while the 18-month backfill is still running?

I would not silently mix transformation versions inside one backfill run. The current RUN ID keeps its pinned transformation version so all completed outputs remain reproducible. If the new logic must apply to historical data, I would create a new manifest and RUN ID with the new transformation version and define exactly which partitions must be recomputed. Those partitions would go through the same lease, canonical transformation, staging, validation, checkpoint, and atomic-promotion path. Version checks during promotion prevent an older run from overwriting a newer accepted result.

How would you finish the backfill faster when spare production capacity changes throughout the day?

I would use adaptive concurrency. The orchestrator can increase backfill parallelism when production SLA, lag, and shared-resource utilization are comfortably inside their guardrails, then reduce or pause historical workers as production load rises. Partition leases still prevent duplicate ownership, and each partition keeps the same idempotent staging, validation, checkpoint, and version-checked atomic promotion rules. This uses quiet periods efficiently without weakening the requirement that today's production run always has priority.

65. Design a bounded streaming join between clicks and impressions with late and duplicate events.Data EngineeringHard

Question Details

Both streams contain stable event IDs, user_id, session_id, and event time; either side may arrive first, events may be retried, and lateness has a declared maximum. Define join keys and cardinality, event-time watermarks, per-key state, state TTL, deduplication window, unmatched and too-late handling, idempotent sink keys, checkpoint and replay semantics, memory and skew controls, quality metrics, and a batch correction path for events outside the bound.

Short Interview Answer (30-60 seconds)

Deduplicate by event_id, key both streams by (user_id, session_id), and join with a bounded event-time predicate. Use per-stream watermarks to close state safely, deterministic sink keys for replay, side outputs for beyond-bound events, coordinated checkpoints, and a batch correction path for data outside the streaming bound.

Detailed Explanation

We need to match each click with the impression or impressions that could have caused it, even when records arrive in the wrong order or are sent more than once. We cannot keep every record forever, so we define how long a possible match remains open. Once enough time has passed, we safely finish the result and remove old records. Repeated records must not create repeated results. Very delayed records are saved separately and corrected later. The design must also recover safely after failures and prevent unusually busy users or sessions from consuming unlimited memory.

Useful Questions to Ask the Interviewer
  1. What is the declared maximum lateness L for each input stream?
  2. What business matching horizon W should relate an impression to a click?
  3. Can one impression match several clicks and can one click match several impressions, or should an attribution rule choose one match?
  4. Should we emit unmatched impressions, unmatched clicks, or both?
  5. How long can producers, consumers, or recovery replay the same event_id?
  6. Does the destination support transactional writes or deterministic upserts?
  7. How quickly must events outside the streaming bound be corrected?
Design a bounded streaming join between clicks and impressions with late and duplicate events. diagram
How to Explain It in an Interview

Start with the contracts. Each click and impression contains a stable event_id, user_id, session_id, and event_time. event_id is the deduplication identity. Repartition both streams by the logical join key (user_id, session_id) so records that may match are processed together. The output grain is one row per valid impression-click pair unless the business contract defines a narrower attribution rule.

Use an explicit directional event-time predicate. In the design shown in the diagram, a pair is valid when impression_time <= click_time <= impression_time + W. W is the maximum attribution horizon after an impression. This is different from a vague symmetric window. If several impressions and clicks occur in the same session, the join can be many-to-many, so a session with I eligible impressions and C eligible clicks can produce as many as I x C pairs unless the business contract narrows the match.

Deduplicate each input before the join using its stable event_id. Keep seen IDs for at least the declared retry, replay, and lateness horizon. That deduplication state must itself be bounded. A duplicate that arrives after the retained ID has expired can appear again, which is why deterministic output keys are still necessary.

Use event time for matching, not processing or arrival time. Conceptually maintain one watermark per stream, such as WM_click = max observed click event_time - L and WM_imp = max observed impression event_time - L. In a distributed implementation, watermark generation and aggregation must respect partitions. Join progress is limited by the minimum watermark among active inputs. If an input or partition can become idle, configure an appropriate idleness policy so a genuinely inactive input does not stall event-time progress forever.

Keep unmatched impressions and clicks in per-key state. For an impression at time t, a valid click can arrive through event time t + W, so keep that impression until the click-side watermark has passed t + W. For a click at time c, valid impressions have event times from c - W through c, so keep the click until the impression-side watermark has passed c. These opposite-watermark tests are the event-time correctness boundary. If the chosen engine offers a processing-time TTL, it can be an additional safety cap, but it must not expire state earlier than these event-time conditions allow.

When a valid pair is found, emit a joined record with the source IDs and required business fields. Use a deterministic matched-output key such as (impression_event_id, click_event_id). Write to a destination that supports transactional writes or deterministic idempotent upserts. If unmatched records are persisted, key them deterministically by output type, source side, and event_id. If too-late records are persisted, use a deterministic key based on source side and event_id. This prevents recovery or retries from multiplying business records.

Do not classify a record as unmatched just because its partner has not arrived yet. Emit an unmatched impression only after the click watermark proves its final valid click time has passed. Emit an unmatched click only after the impression watermark proves its latest possible impression time has passed. An event that arrives after the system has already finalized the relevant event-time horizon is beyond the streaming bound. Send it to a too-late side output or quarantine path instead of silently changing finalized online results.

For recovery, use a stream processor that can coordinate source positions with deduplication and join state in the same checkpoint. After a failure, restore the checkpoint and replay records after the saved source positions. Checkpointing does not by itself guarantee exactly-once business outcomes: the sink must also participate transactionally or make repeated writes deterministic and idempotent.

Bound memory in three ways. First, remove join state when the opposite watermark closes its matching horizon. Second, expire deduplication IDs after the required retry and replay horizon. Third, watch per-key state size. A hot (user_id, session_id) can create both large state and many output pairs. Monitor records and bytes per key and pair-expansion rate. If skew is severe, use a business-valid secondary key when one exists or isolate pathological keys into a separate processing path. Do not blindly salt the join key because that can separate events that must meet.

Track watermark lag, duplicate rate, late and too-late rate, match and unmatched rate, state records and bytes per key, hot-key frequency, checkpoint or recovery failures, and sink conflicts or replay duplicates. These metrics reveal stalled event-time progress, a poor lateness assumption, state growth, skew, and idempotency problems.

Retain immutable raw impressions and clicks outside the bounded online state. Periodically run a batch correction over events that fell outside L. Reapply the same join key and the same predicate impression_time <= click_time <= impression_time + W. Write corrected rows with the same deterministic sink keys so the correction performs upserts instead of creating a second copy of the result.

The main tradeoff is between latency, memory, and correction volume. Larger W keeps more possible matches and can increase state and pair explosion. Larger L waits for more delayed records online but keeps state longer and delays finalization. Smaller bounds reduce online state and latency but move more records into the batch correction path.

Technical Approach
  1. Validate the input contract: stable event_id, user_id, session_id, and event_time.
  2. Deduplicate each stream by event_id with retention covering the declared retry, replay, and lateness horizon.
  3. Repartition both streams by (user_id, session_id).
  4. Apply the directional predicate impression_time <= click_time <= impression_time + W and confirm its potentially many-to-many cardinality.
  5. Maintain event-time watermarks for both streams and derive join progress from the minimum active-input watermark.
  6. Buffer unmatched events per key.
  7. Evict an impression only after the click watermark passes impression_time + W; evict a click only after the impression watermark passes click_time.
  8. Emit valid matches using deterministic pair keys.
  9. Emit unmatched records only after the opposite watermark closes the complete matching horizon.
  10. Route events arriving beyond the finalized streaming bound to a too-late side output.
  11. Coordinate source positions, deduplication state, and join state in checkpoints and use transactional or deterministic-idempotent sink writes during replay.
  12. Monitor state size, hot keys, pair explosion, watermark lag, duplicates, late data, and sink conflicts.
  13. Retain immutable raw data and batch-rejoin events outside L, then upsert corrections with the same deterministic sink keys.
Practical Insights

For each normal event, the system performs a deduplication lookup, updates keyed state, and examines possible matches on the other side. With an efficient time-indexed state structure, irrelevant records can be avoided, but every valid output pair still has to be produced. For a hot session with I eligible impressions and C eligible clicks, a many-to-many relationship can create as many as I x C outputs. Memory grows with the unmatched events and deduplication IDs retained inside their horizons. Larger W or L usually increases state and delays finalization. Larger state also increases checkpoint, recovery, and operational cost.

Why Interviewers Ask This

This question tests whether the candidate can reason about correctness in a stateful stream-stream join when records are duplicated, arrive out of order, or arrive late. A strong answer connects event-time semantics, watermarks, join cardinality, bounded state, deduplication, deterministic output, recovery, skew protection, quality monitoring, and correction of records that fall outside the online lateness bound.

Common interview mistakes

Common mistakes are joining only on user_id and mixing unrelated sessions; assuming one-to-one cardinality without a business rule; using processing time instead of event time; defining an ambiguous symmetric window instead of an explicit directional predicate; using only one stream's watermark; forgetting that distributed watermark progress depends on input partitions; expiring impression and click state with one arbitrary TTL instead of proving the opposite watermark has closed the matching horizon; treating processing-time TTL as the event-time correctness boundary; assuming event_id deduplication makes sink writes automatically idempotent; claiming checkpoints alone guarantee exactly-once business results; emitting unmatched rows too early; silently dropping beyond-bound events; retaining state forever; blindly salting hot join keys; ignoring many-to-many pair explosion; and using different predicates or sink keys in the batch correction path.

Interview tip

Start with four invariants: the join key, the directional event-time predicate, the lateness bound, and the output grain. Then explain exactly when each side's state can be deleted and how recovery avoids duplicate sink rows. Finish with the W-versus-L tradeoff, hot-key risk, quality metrics, and batch correction path.

Interviewer may ask next
How would you choose the watermark lateness bound L and the join horizon W?

Choose W from the business relationship: it defines how long after an impression a click can still be a valid match. Choose L from measured arrival-delay behavior and the acceptable online finalization latency. They solve different problems. A larger W allows more possible pairs and retains join state longer. A larger L accepts more delayed events online but also delays finalization and usually retains state longer. I would track event-time delay distributions, watermark lag, too-late rate, state size, output expansion, and batch correction volume, then choose bounds that meet the product's correctness, latency, and cost goals.

What happens if one user or session becomes extremely hot and creates millions of possible impression-click pairs?

Detect it with per-key state bytes, record counts, pair counts, and output-expansion metrics. Do not blindly salt (user_id, session_id), because different salts can prevent records that should match from meeting. If the contract has a correctness-preserving secondary dimension, use it to narrow partitioning or matching. Otherwise isolate pathological keys into a controlled processing path or apply business-approved limits. Also remember that skew is not only a memory problem: a many-to-many join can create I x C output rows, so the destination and correction path must tolerate or deliberately constrain that expansion.

66. What is a SQL join, and how do INNER JOIN and LEFT JOIN differ?Sql And DatabaseEasy

Question Details

Define a relational join using matching keys from two tables. Compare the rows retained by INNER JOIN and LEFT JOIN, explain how unmatched rows and NULL values appear, show how one-to-many relationships can multiply rows, and describe the validation checks you would use to prevent an accidental overcount.

Short Interview Answer (30-60 seconds)

A SQL join combines rows from two tables using a matching key. INNER JOIN keeps only matching rows. LEFT JOIN keeps all rows from the left table and matching rows from the right; unmatched right-side columns become NULL. One-to-many matches can multiply rows, so validate the result grain.

Detailed Explanation

See the Code while reading this explanation.

A SQL join combines related information from two tables by matching a shared value. The main difference is which rows remain. With one type, only records that have a match on both sides stay in the result. With the other type, every record from the first table stays even when there is no match in the second table. You must also watch for one record matching several records, because that creates extra result rows and can make counts or totals too large if you do not check the final level of detail.

Useful Questions to Ask the Interviewer
  1. Should I assume the join condition is equality on a matching customer identifier?
  2. Should customers with no matching orders remain in the result?
  3. What should the final result grain be: one row per customer or one row per customer-order match?
  4. Should I explain how to detect row multiplication before aggregating?
What is a SQL join, and how do INNER JOIN and LEFT JOIN differ? diagram
How to Explain It in an Interview

Assume standard SQL and the diagram's example: customers is the left table, orders is the right table, and the tables match on customers.customer_id = orders.customer_id.

A join combines rows when the join condition matches. In this example, one customer can have many orders, so the relationship is one-to-many.

With INNER JOIN, only rows with a match in both tables remain. Alice has two matching orders, so Alice appears twice. Bob and Dave have matching orders and appear once each. Carol has no matching order, so Carol does not appear in the INNER JOIN result.

With LEFT JOIN, every row from customers remains. Alice still appears twice because two orders match. Bob and Dave appear with their matching orders. Carol also remains, but because no order matches Carol, the columns from orders, such as order_id and amount, are NULL.

The important analytical risk is row multiplication. If one customer has N matching orders, that customer can produce N joined rows. Therefore, a join can increase the number of rows. If you later use COUNT(*) or sum a value that exists once per customer, the result may be too large.

To validate the join, first define the intended grain. Then compare row counts before and after the join, count distinct left-table keys, and check for unmatched LEFT JOIN rows by testing a right-table key for NULL. Finally, aggregate at the intended level instead of assuming the raw joined rows already have the correct grain.

Technical Approach
  1. Identify the left table, right table, and matching key.
  2. Define the intended result grain before joining.
  3. Use INNER JOIN when only rows with matches on both sides should remain.
  4. Use LEFT JOIN when every row from the left table must remain.
  5. Expect NULL in right-table columns for unmatched LEFT JOIN rows.
  6. Check whether the relationship is one-to-one or one-to-many because multiple matches can multiply rows.
  7. Compare row counts before and after the join.
  8. Count distinct left-table keys to detect unexpected duplication.
  9. Check unmatched rows using a right-table key that is NULL after the LEFT JOIN.
  10. Aggregate at the intended grain to avoid overcounting.
Practical Complexity & Trade-offs

The logical meaning of the join does not depend on a specific physical algorithm, but the database may need to read and compare many rows. One-to-many matches can also create a larger result than the input tables, which increases processing, memory, and data-transfer cost. The main analytical cost is correctness: repeated left-side values can inflate counts or sums. Indexes and join algorithms can affect speed, but an index does not always make a join faster. The diagram is conceptual and does not define a database engine, dataset size, or performance limit.

Example

The example uses standard SQL with customers as the left table and orders as the right table. The join key is customer_id. INNER JOIN returns one row for each matching customer-order pair and excludes customers without a match. LEFT JOIN returns the same matching rows but also preserves unmatched customers, with NULL in the right-table columns. Because Alice has two matching orders, Alice appears twice, demonstrating one-to-many row multiplication. The explicit ORDER BY makes the teaching output deterministic.

Code
-- Standard SQL assumption.
-- Result grain: one row per customer-order match.
-- Join key: customers.customer_id = orders.customer_id.
-- Null handling: unmatched right-side columns are NULL only in the LEFT JOIN result.
-- This is a read-only example, so no transaction boundary or parameter binding is needed.
-- INNER JOIN keeps only rows that have a match in both tables.
SELECT
  c.customer_id,
  c.customer_name,
  o.order_id,
  o.amount
FROM
  customers AS c
  INNER JOIN orders AS o ON c.customer_id = o.customer_id
  -- Order by customer and order so the example output is stable and easy to verify.
ORDER BY
  c.customer_id,
  o.order_id;


-- LEFT JOIN preserves every customer from the left table.
-- If no order matches, o.order_id and o.amount are NULL.
SELECT
  c.customer_id,
  c.customer_name,
  o.order_id,
  o.amount
FROM
  customers AS c
  LEFT JOIN orders AS o ON c.customer_id = o.customer_id
  -- Use the same ordering so INNER JOIN and LEFT JOIN results are easy to compare.
ORDER BY
  c.customer_id,
  o.order_id;
Where it is used

INNER JOIN is useful when an analysis should include only entities that have related records, such as customers that placed orders. LEFT JOIN is useful when the complete population from a primary table must remain, such as all customers including those without orders. Data scientists commonly use these joins when combining customer data with transactions, preparing analytical datasets, creating features, checking missing relationships, and building reports.

Why Interviewers Ask This

This question checks whether the candidate understands how relational tables are combined, which rows INNER JOIN and LEFT JOIN retain, how NULL values represent unmatched right-side data, and how one-to-many relationships affect result grain. It also tests practical analytical judgment: recognizing that joins can multiply rows and validating row counts, distinct keys, unmatched rows, and aggregation grain before trusting counts or sums.

Common interview mistakes

Common mistakes are saying LEFT JOIN keeps only matching rows, forgetting that unmatched right-side columns become NULL, and assuming a join preserves the original row count. Another mistake is ignoring one-to-many relationships, which can repeat a left-table row once for every matching right-table row and inflate counts or sums. Analysts also sometimes check only total row count instead of distinct keys and intended grain. A further mistake is filtering a right-table column in the WHERE clause after a LEFT JOIN in a way that removes NULL rows, unintentionally discarding unmatched left-table records.

Interview tip

Start with the retention rule: INNER JOIN keeps matches only; LEFT JOIN preserves every left-table row. Then explain NULLs for unmatched right rows. Use the one-to-many example to show why row counts can increase, and finish with concrete validation checks: grain, row count, distinct keys, unmatched rows, and aggregation level.

Interviewer may ask next
Why can a one-to-many join cause an accidental overcount?

If one left-table row matches several right-table rows, the left-side information is repeated once for each match. In the diagram, Alice has two orders, so Alice appears twice. If a customer-level value is then counted or summed across those joined rows, Alice's value may be counted more than once. Prevent this by defining the intended grain, checking row counts and distinct keys, and aggregating at the correct level.

How can a WHERE clause accidentally change the behavior of a LEFT JOIN?

A LEFT JOIN preserves unmatched left rows by returning NULL in the right-table columns. If a later WHERE condition requires a right-table column to equal a non-NULL value, those unmatched rows fail the condition and disappear. When unmatched left rows must remain, put the appropriate right-table matching condition in the ON clause or explicitly handle NULL values in the filter.

67. Find products that are both low fat and recyclable.Sql And DatabaseEasy

Question Details

Use MySQL 8.0. Table Products(product_id INT PRIMARY KEY, low_fats ENUM('Y','N') NOT NULL, recyclable ENUM('Y','N') NOT NULL) has one row per product and no duplicates. Return one column named product_id for rows where both flags are Y; row order is unrestricted and null handling is unnecessary because the flags are non-null. Example rows (0,'Y','N'),(1,'Y','Y'),(2,'N','Y'),(3,'Y','Y') must return product IDs 1 and 3.

Short Interview Answer (30-60 seconds)

Filter the Products table with both conditions joined by AND, then return only product_id. Use SELECT product_id FROM Products WHERE low_fats = 'Y' AND recyclable = 'Y';. For the given rows, the matching product IDs are 1 and 3.

Detailed Explanation

See the Code while reading this explanation.

We have a list of products, and every product has two yes-or-no properties. We need only the products for which both properties are yes at the same time. A product must not be returned when only one property is yes. We return only its product number. Each product appears once, so repeated rows do not need to be removed. The two properties always contain a value, so missing values need no special handling. The result does not need a particular order. In the supplied example, the matching product numbers are 1 and 3.

Useful Questions to Ask the Interviewer
  1. Should the result contain only product_id, with no required ordering?
  2. Can I rely on low_fats and recyclable being NOT NULL and restricted to 'Y' or 'N'?
Find products that are both low fat and recyclable. diagram
How to Explain It in an Interview

The table grain is one row per product, and product_id is the primary key, so every product is unique. We need the same row to satisfy two predicates: low_fats = 'Y' and recyclable = 'Y'. Because both conditions must be true, the WHERE clause uses AND. The SELECT clause projects only product_id because that is the required result column.

The MySQL 8.0 query is:

SELECT product_id FROM Products WHERE low_fats = 'Y' AND recyclable = 'Y';

For the example data, product 1 has ('Y','Y') and product 3 has ('Y','Y'), so both qualify. Product 0 fails because recyclable is 'N'. Product 2 fails because low_fats is 'N'. Therefore, the result contains product IDs 1 and 3. No ORDER BY is required, so MySQL is free to return the matching rows in any order. No NULL handling is needed because low_fats and recyclable are declared NOT NULL.

The execution flow is straightforward. An analytical client, such as a SQL editor or notebook, sends the SQL query through a MySQL connector. Inside the MySQL 8.0 server, the parser validates the SQL, the optimizer chooses a physical execution plan, and the executor runs that plan against the Products table stored by InnoDB. The server then returns a result set containing only product_id to the client. This is a read-only SELECT, so there is no application data change, commit, or rollback required for the answer.

Logically, the important operation is simply filtering rows where both flags equal 'Y' and projecting product_id. Physically, MySQL may scan the table or use an index depending on available indexes, statistics, and data distribution. InnoDB stores the table using the product_id primary key as its clustered primary index, but that primary-key index does not directly filter low_fats and recyclable. If this query becomes frequent on a large table, a composite index such as (low_fats, recyclable, product_id) can be evaluated. Because the two filter columns contain only Y/N values, they have low selectivity, so the index is not guaranteed to be faster and should be verified against the real workload.

Technical Approach
  1. Start from Products, which has one row per product.
  2. Apply the condition low_fats = 'Y'.
  3. Require recyclable = 'Y' on the same row by joining the conditions with AND.
  4. Project only product_id from the matching rows.
  5. Do not add DISTINCT because product_id is unique and there are no duplicate product rows.
  6. Do not add NULL handling because both flags are NOT NULL.
  7. Do not add ORDER BY because result order is unrestricted.
  8. For the sample data, return product IDs 1 and 3.
Practical Complexity & Trade-offs

If MySQL has no useful index for these two filter columns, it may examine all n rows, so the work is approximately O(n). The query returns only one integer column for each matching row, so data-transfer cost depends on how many products match. The existing primary-key index on product_id guarantees unique IDs but does not directly optimize these filters. A composite index such as (low_fats, recyclable, product_id) may help some large, frequently queried tables, but it adds storage and write-maintenance cost. Because low_fats and recyclable each have only two values, the index may have low selectivity and should be tested rather than assumed to help.

Example

The standalone MySQL 8.0 query returns exactly one column, product_id. The WHERE clause uses AND because both flags must equal 'Y' on the same Products row. DISTINCT is unnecessary because product_id is a primary key and the table has one row per product. NULL handling is unnecessary because both flags are NOT NULL. ORDER BY is intentionally omitted because the required row order is unrestricted.

Code
-- Return exactly one column, so the result grain is one product_id per matching product.
SELECT
  product_id
FROM
  Products
  -- Both flags are NOT NULL, so no special NULL handling is required.
  -- AND keeps only rows where both required conditions are true on the same product.
WHERE
  low_fats = 'Y'
  AND recyclable = 'Y';
Where it is used

This SQL pattern is used when a database must return entities that satisfy multiple attributes at the same time. Examples include products that are active and in stock, customers who are verified and subscribed, or records that satisfy two eligibility flags. In this exact case, it returns product IDs whose low_fats and recyclable values are both 'Y'.

Why Interviewers Ask This

This question checks whether the candidate can translate two simultaneous business conditions into a correct SQL filter, return only the requested column, understand the one-row-per-product table grain, and reason correctly about non-null flags and unrestricted result ordering.

Common interview mistakes

Common mistakes include using OR instead of AND, which would return products satisfying only one condition; selecting all columns instead of only product_id; adding DISTINCT even though product_id is unique and the table has one row per product; adding unnecessary NULL logic despite both flags being NOT NULL; assuming output order without ORDER BY; or claiming that the primary-key index on product_id directly speeds up filtering on low_fats and recyclable.

Interview tip

State the decision first: both flags must be 'Y', so use AND. Then write the short query and explain why DISTINCT, NULL handling, and ORDER BY are unnecessary under the supplied constraints. If performance comes up, separate the logical SQL meaning from MySQL's physical execution plan and do not claim that an added index will automatically be faster.

Interviewer may ask next
How would the query change if products that are either low fat or recyclable should be returned?

Replace AND with OR: SELECT product_id FROM Products WHERE low_fats = 'Y' OR recyclable = 'Y';. OR means a row qualifies when at least one of the two flags is 'Y', so this returns more rows than the original both-conditions query.

Would adding a composite index on low_fats and recyclable always make this query faster?

No. Both columns contain only 'Y' or 'N', so they have low selectivity and an index may still match a large part of the table. For a large table where this query is frequent, an index such as (low_fats, recyclable, product_id) can be evaluated, but its benefit depends on the data distribution, number of matching rows, table size, statistics, and workload. Measure the real execution plan and performance instead of assuming the index is beneficial.

68. Find customers who were not referred by customer 2.Sql And DatabaseEasy

Question Details

Use MySQL 8.0. Table Customer(id INT PRIMARY KEY, name VARCHAR(25) NOT NULL, referee_id INT NULL) has one row per customer; referee_id may be null and duplicates do not occur. Return one column named name for every customer whose referee_id is not 2, including customers with null referee_id; row order is unrestricted. Example rows (1,'Will',NULL),(2,'Jane',NULL),(3,'Alex',2),(4,'Bill',NULL),(5,'Zack',1),(6,'Mark',2) must return Will, Jane, Bill, and Zack.

Short Interview Answer (30-60 seconds)

I would select names where referee_id is different from 2 or is NULL. In MySQL 8.0, the condition is referee_id <> 2 OR referee_id IS NULL. This returns Will, Jane, Bill, and Zack.

Detailed Explanation

See the Code while reading this explanation.

We need to return the names of customers who were not referred by customer 2. A customer may also have no referee, and those customers must still be included. In the example, Alex and Mark were referred by customer 2, so we leave them out. Will, Jane, and Bill have no referee, while Zack was referred by customer 1, so all four stay. The final result therefore contains Will, Jane, Bill, and Zack. The question says row order is unrestricted, so these names may appear in any order.

Useful Questions to Ask the Interviewer
  1. Should customers with no referee be included? Yes. The question explicitly says to include rows where referee_id is NULL.
  2. Does the output need a particular order? No. Row order is unrestricted.
Find customers who were not referred by customer 2. diagram
How to Explain It in an Interview

The Customer table has one row per customer. id is the primary key, name is VARCHAR(25) NOT NULL, and referee_id is an INT that may be NULL. The required result has exactly one column named name.

The important part is SQL NULL handling. In this question, a NULL referee_id means the customer has no referee. The expression referee_id <> 2 is not TRUE when referee_id is NULL. It evaluates to UNKNOWN, and a WHERE clause keeps only rows whose condition evaluates to TRUE. Therefore, using only referee_id <> 2 would incorrectly remove Will, Jane, and Bill.

The correct predicate has two alternatives: keep a row when referee_id <> 2, or keep it when referee_id IS NULL. Alex and Mark have referee_id = 2, so they are excluded. Zack has referee_id = 1, so he is included. Will, Jane, and Bill have NULL, so the explicit IS NULL branch includes them.

The diagram's execution flow is also consistent with this query. The analytical client sends the SQL to the MySQL 8.0 SQL engine. The optimizer chooses an access path. The storage engine reads the needed Customer rows, the filter condition is applied, and the qualifying rows are returned as the one-column result. No index on referee_id is specified, so the answer must not assume one. An index is not required for correctness. No ORDER BY is needed because row order is unrestricted.

Technical Approach

1. Read from Customer, which has one row per customer. 2. Evaluate whether referee_id is different from 2. 3. Explicitly include rows where referee_id is NULL because a normal comparison with NULL does not evaluate to TRUE. 4. Return only the name column. 5. Do not add ordering because the question says row order is unrestricted.

Practical Complexity & Trade-offs

The supplied schema does not specify an index on referee_id, so no index-based access path should be assumed. MySQL may inspect the Customer rows and evaluate the filter for each row, which is roughly O(N) row checks for N customers. The query needs no sorting because row order is unrestricted and no grouping or join work is required. An index is not needed for correctness. In production, whether an index would help depends on table size, data distribution, workload, and the optimizer's chosen plan.

Example

The query returns only the name column, matching the required result grain. referee_id <> 2 keeps customers referred by someone other than customer 2. OR referee_id IS NULL is necessary because comparisons involving NULL do not evaluate to TRUE. Together, the conditions include Will, Jane, Bill, and Zack and exclude Alex and Mark.

Code
-- Return exactly one output column, name, for each qualifying customer row.
-- Keep customers referred by someone other than customer 2.
-- Explicitly include NULL because NULL <> 2 does not evaluate to TRUE in SQL.
SELECT
  name
FROM
  Customer
WHERE
  referee_id <> 2
  OR referee_id IS NULL;
Where it is used

This pattern is useful when an optional relationship is stored in a nullable column and an analysis must exclude one specific related entity while keeping records with no relationship. Examples include selecting users not assigned to one referrer, orders not attributed to one partner, or records whose optional parent is either different from a target value or NULL.

Why Interviewers Ask This

This question tests whether the candidate understands SQL filtering and NULL behavior. The key judgment is recognizing that referee_id <> 2 alone does not include rows where referee_id is NULL. It also checks whether the candidate preserves the requested result grain of one name column per qualifying customer without adding unnecessary joins, grouping, ordering, indexes, or unsupported schema assumptions.

Common interview mistakes

The main mistake is writing only WHERE referee_id <> 2. That incorrectly excludes rows where referee_id is NULL. Another mistake is using referee_id = NULL or referee_id <> NULL; SQL requires IS NULL or IS NOT NULL for NULL checks. Candidates may also add an unnecessary join, grouping, or ordering even though the needed values are already in Customer, duplicates do not occur, and row order is unrestricted. Do not claim that referee_id has an index or foreign-key constraint because neither is specified.

Interview tip

State the NULL issue immediately: <> 2 alone is not enough because a NULL comparison does not evaluate to TRUE. Then give referee_id <> 2 OR referee_id IS NULL and verify it quickly against Alex, Mark, Zack, and one NULL row.

Interviewer may ask next
Why does WHERE referee_id <> 2 not return customers whose referee_id is NULL?

SQL uses three-valued logic: TRUE, FALSE, and UNKNOWN. When referee_id is NULL, referee_id <> 2 evaluates to UNKNOWN rather than TRUE. A WHERE clause keeps only rows for which the condition is TRUE, so NULL rows are excluded unless the query explicitly adds OR referee_id IS NULL.

Would adding an index on referee_id make this query faster?

An index is not required for correctness, and the supplied schema does not specify one. On a larger real table, an index on referee_id might help some workloads, but the benefit depends on data distribution, selectivity, table size, and the MySQL optimizer's chosen access path. An index also adds storage and write-maintenance cost, so it should be justified with workload evidence rather than assumed.

69. Return countries that are large by area or population.Sql And DatabaseEasy

Question Details

Use MySQL 8.0. Table World(name VARCHAR(255) PRIMARY KEY, continent VARCHAR(255) NOT NULL, area INT NOT NULL, population INT NOT NULL, gdp BIGINT NOT NULL) has one row per country. A country is large when area >= 3000000 or population >= 25000000. Return columns name, population, and area; row order is unrestricted and there are no nulls or duplicate country rows. Example input rows ('Afghanistan','Asia',652230,25500100,20343000000), ('Albania','Europe',28748,2831741,12960000000), ('Algeria','Africa',2381741,37100000,188681000000), ('Andorra','Europe',468,78115,3712000000), and ('Angola','Africa',1246700,20609294,100990000000) must return ('Afghanistan',25500100,652230) and ('Algeria',37100000,2381741).

Short Interview Answer (30-60 seconds)

Select name, population, and area from World, then filter with OR because meeting either threshold is enough. Use >= so exact boundary values qualify. With the supplied rows, Afghanistan and Algeria are returned because each has population of at least 25,000,000.

Detailed Explanation

See the Code while reading this explanation.

We need to find countries that satisfy at least one of two rules. A country should be returned when its area is 3,000,000 or more, or when its population is 25,000,000 or more. Meeting only one rule is enough. We should show only the country name, population, and area. Each country appears once, and the supplied data has no missing values. The order of the returned countries does not matter. In the sample, Afghanistan and Algeria pass because their populations are above the required population threshold.

Useful Questions to Ask the Interviewer
  1. Should countries exactly equal to 3,000,000 in area or 25,000,000 in population be included? Yes. The supplied conditions use greater than or equal to.
  2. Is a particular output order required? No. Row order is unrestricted.
Return countries that are large by area or population. diagram
How to Explain It in an Interview

The table is World in MySQL 8.0. It has one row per country, and name is the primary key. All five columns are NOT NULL, so no extra null handling is needed. The primary key also means country names are unique, and the question states there are no duplicate country rows.

The key decision is to use OR, not AND. OR means a country qualifies when either area >= 3000000 or population >= 25000000 is true. Using AND would be too restrictive because it would require both conditions to be true.

The query selects exactly name, population, and area. It does not need a join, aggregation, grouping, deduplication, transaction, or ORDER BY because the problem uses one table, one row per country, and unrestricted result order.

The execution flow shown in the diagram is: the Data Scientist analytical client submits the SQL through a MySQL Connector, the connector sends the query to the MySQL 8.0 query engine, the engine parses, optimizes, and executes it against the World table in storage, and the matching result set is returned through the connector to the client.

For the supplied rows, Afghanistan has population 25,500,100, so it qualifies even though its area is only 652,230. Algeria has population 37,100,000, so it also qualifies even though its area is 2,381,741. Albania, Andorra, and Angola meet neither threshold.

For performance, a full table scan can be reasonable for a small table. On a much larger table, indexes on area and population may help some execution plans, but an OR across separate columns does not guarantee efficient use of both indexes. MySQL can choose different strategies depending on data distribution and selectivity. In production, use EXPLAIN and measured execution time before changing indexes or considering larger physical-design changes such as partitioning.

Technical Approach
  1. Read rows from World logically.
  2. Test whether area >= 3000000.
  3. Test whether population >= 25000000.
  4. Keep the row when either condition is true.
  5. Return only name, population, and area.
  6. Do not add sorting because result order is unrestricted.
Time & Space Complexity

Without a useful index plan, MySQL may examine every row, so the work grows roughly with the number of countries in the table. No join, grouping, sorting, or application-side data structure is required. Separate indexes on area and population can add storage and write-maintenance cost, and they do not automatically make this OR query faster. For a large production table, verify the actual MySQL plan with EXPLAIN and benchmark realistic data before adding or changing indexes.

Example

The MySQL 8.0 query returns one row for every country that meets at least one threshold. The SELECT list contains only name, population, and area. The WHERE clause uses OR, so either condition is sufficient. The >= operators include values exactly on the thresholds. No join, grouping, deduplication, transaction, parameter binding, or sorting is required for this read-only query with fixed numeric thresholds and unrestricted row order.

Code
-- Return one result row per qualifying country and only the requested columns.
-- No JOIN or GROUP BY is needed because World already has one row per country.
-- No extra NULL or duplicate handling is needed because the supplied schema/data rules exclude them.
SELECT
  name,
  population,
  area
FROM
  World
  -- OR is required: meeting either threshold is sufficient.
  -- >= includes countries exactly on either boundary.
WHERE
  area >= 3000000
  OR population >= 25000000;


-- No ORDER BY is required because output order is unrestricted.
-- No explicit transaction boundary or parameter binding is needed for this read-only query with fixed constants.
Where it is used

This exact filtering pattern is used in analytical reports, dashboards, segmentation, and feature preparation when a record qualifies by either of two independent thresholds. Similar examples include finding markets with high revenue or many customers, products with high sales or high inventory, and regions that qualify by either population or geographic size.

Why Interviewers Ask This

This question checks whether the candidate can translate two business thresholds into a correct MySQL 8.0 filter, choose OR instead of AND, return only the requested columns, preserve the one-row-per-country grain, handle inclusive boundaries correctly, and discuss basic query execution and performance without adding unnecessary SQL operations.

Common interview mistakes

The main mistake is using AND instead of OR, which incorrectly requires a country to meet both thresholds. Other mistakes include using > instead of >= and excluding exact boundary values, returning extra columns such as continent or gdp, adding unnecessary joins or grouping, adding ORDER BY when no order is required, or inventing null and duplicate handling even though the problem explicitly rules those cases out. A performance mistake is claiming that indexes on both filtered columns will always make the query faster; the optimizer, table size, selectivity, and data distribution determine the physical execution plan.

Interview tip

Start with the main decision: use OR because either condition is enough. Then write the short MySQL query, explain the inclusive >= boundaries, verify Afghanistan and Algeria from the sample, and mention that any indexing decision should be validated with the actual MySQL execution plan.

Interviewer may ask next
What changes if a country must be large by both area and population?

Replace OR with AND: WHERE area >= 3000000 AND population >= 25000000. A country would then be returned only when both conditions are true. In the supplied sample, neither Afghanistan nor Algeria meets both thresholds, so neither would be returned.

Would indexes on area and population always make this OR query faster?

No. Separate indexes on area and population may help on a large table, and MySQL can sometimes use index-based strategies for OR predicates, but usefulness depends on table size, selectivity, data distribution, and optimizer cost estimates. A small table may still be faster with a full scan. Use EXPLAIN and measured execution time before adding indexes specifically for this query.

70. Find authors who viewed at least one of their own articles.Sql And DatabaseEasy

Question Details

Use MySQL 8.0. Table Views(article_id INT NOT NULL, author_id INT NOT NULL, viewer_id INT NOT NULL, view_date DATE NOT NULL) may contain duplicate rows and has no primary key; each row is one recorded view. Return distinct matching author_id values where author_id = viewer_id, rename the output column to id, and sort it ascending. Example rows containing self-views by authors 4 and 7, including repeated self-view records, must return exactly id values 4 and 7 once each.

Short Interview Answer (30-60 seconds)

Use WHERE author_id = viewer_id to keep self-views, DISTINCT to return each matching author once, AS id to rename the column, and ORDER BY id ASC to sort ascending. For the example data, the result is exactly 4 and 7.

Detailed Explanation

See the Code while reading this explanation.

We need to find people who looked at something they wrote themselves. Each row is one recorded view. Some rows can be repeated, so the same person may appear more than once. First, keep only rows where the writer and the viewer are the same person. Then return each matching person only once. Rename the returned column to id and put the values in increasing order. In the example, authors 4 and 7 viewed their own articles, so the final result contains only 4 and 7, one time each.

Useful Questions to Ask the Interviewer
  1. Should each author appear only once even if that author has several self-view records? Yes. The requirement says to return distinct matching author IDs.
  2. Is ascending order required in the final output? Yes. The returned id values must be sorted ascending.
Find authors who viewed at least one of their own articles. diagram
How to Explain It in an Interview

The Views table has the schema Views(article_id INT NOT NULL, author_id INT NOT NULL, viewer_id INT NOT NULL, view_date DATE NOT NULL). It has no primary key, duplicate rows may exist, and each row represents one recorded view.

The key condition is author_id = viewer_id. When that condition is true, the author of the article is also the viewer, so the row represents a self-view.

Because the table may contain duplicate rows or an author may have several self-view records, returning every matching row could repeat the same author. DISTINCT author_id removes those repeated author values and makes the result grain one row per qualifying author.

AS id renames the output column exactly as required. ORDER BY id ASC sorts the final IDs from smallest to largest. For the example shown in the diagram, repeated self-view records for authors 4 and 7 still produce exactly two rows: 4 and 7.

At a high level, an analyst or client sends the SQL through a MySQL client or driver. MySQL 8.0 parses and optimizes the query, reads the relevant Views rows, applies the author_id = viewer_id filter, produces distinct author IDs, sorts them ascending, and returns the result set. The important logical operations are filtering self-views, deduplicating the author IDs, renaming the output column, and sorting the final result.

No join, transaction, grouping, rollback path, or application-side Python code is required for this question. The four columns are NOT NULL, so there is no null-specific case to handle in the equality test.

Technical Approach
  1. Read from Views.
  2. Keep rows where author_id = viewer_id.
  3. Select author_id and apply DISTINCT so each qualifying author appears once.
  4. Rename the selected column to id.
  5. Sort id ascending.
  6. Return the result set, which is 4 and 7 for the supplied example.
Practical Complexity & Trade-offs

The database must examine enough rows to find those where the author and viewer match. Without a useful access path, this can require scanning the table. DISTINCT must remove repeated author IDs, and ORDER BY must put the remaining IDs in ascending order. On large data sets, deduplication and sorting may require extra memory or temporary storage. For this interview question, no additional index is required for correctness.

Example

The MySQL 8.0 query first filters to self-view rows using author_id = viewer_id. DISTINCT removes repeated matching author IDs, including repeats caused by duplicate source rows. AS id gives the required output column name, and ORDER BY id ASC returns the unique IDs in ascending order. Because all relevant columns are NOT NULL, no special null handling is needed.

Code
-- Keep only self-view rows and return one row per qualifying author.
-- DISTINCT removes repeated author IDs caused by multiple or duplicate self-view records.
SELECT DISTINCT
  author_id AS id
FROM
  Views
  -- A self-view occurs when the article author is also the viewer.
WHERE
  author_id = viewer_id
  -- Return the required ascending order of the final distinct IDs.
ORDER BY
  id ASC;
Where it is used

This pattern is useful in analytical event tables when the same entity can appear in two roles and you need entities that interacted with their own content. Examples include creators viewing their own posts, sellers viewing their own listings, or users interacting with records they own. DISTINCT is useful when repeated event rows exist but the report needs one result row per matching entity.

Why Interviewers Ask This

This question tests whether the candidate can translate a simple analytical requirement into correct MySQL. It checks filtering with a column-to-column equality condition, duplicate removal with DISTINCT, output-column aliasing, required ordering, and understanding that the source table can contain duplicate recorded views because it has no primary key.

Common interview mistakes

Common mistakes include omitting DISTINCT and returning author IDs multiple times, comparing the wrong columns, forgetting to rename author_id to id, or omitting the required ascending ORDER BY. Another mistake is adding unnecessary joins or aggregation when the result can be obtained directly from the single Views table. Candidates should also notice that duplicate rows are possible because the table has no primary key.

Interview tip

Explain the query in four simple parts: filter self-views with author_id = viewer_id, deduplicate with DISTINCT, rename the column with AS id, and sort with ORDER BY id ASC. Also mention that repeated self-view rows still produce each matching author only once.

Interviewer may ask next
What happens if the same author has several self-view records or duplicate self-view rows?

The author still appears only once. After WHERE author_id = viewer_id keeps the self-view rows, DISTINCT author_id removes repeated author IDs. For example, multiple matching rows for author 4 still produce one output row with id = 4.

Could GROUP BY author_id be used instead of DISTINCT?

Yes, GROUP BY author_id could also produce one row per matching author in this specific query, but no aggregation is needed. DISTINCT expresses the requirement more directly: keep self-view rows, return unique author IDs, alias the column as id, and sort ascending.

More questions load as you scroll

Disclaimer: This interview guide is for educational and informational purposes only. It is designed to help readers prepare, but it does not guarantee any interview result, hiring decision, offer, or outcome. Interview questions, hiring criteria, and preferred answers can vary by employer, interviewer, industry, location, and time. The examples and explanations reflect the authors' research and judgment, are provided without warranties of any kind, and should not be treated as the only correct approach. Diagrams are simplified illustrations intended to highlight the main components and their interactions; actual systems and implementations may be more complex. Alternative approaches may be equally valid or better suited to a particular question, context, or interviewer. To the fullest extent permitted by applicable law, the author, contributors, and publisher are not liable for decisions made, actions taken, or losses incurred based on this guide.

Content Accuracy and Verification: To the fullest extent permitted by applicable law, we do not represent or warrant that interview guides, questions, answers, examples, or diagrams are accurate, complete, current, error-free, or suitable for any particular purpose. You are responsible for independently reviewing and verifying the information before relying on it.