Skip to content
Reliable Data Engineering
Practice problem medium cdcdeduplicationmerge-logic
Solve it in the browser (SQL editor)

Apply CDC Events to Get the Current Table State

Difficulty: Medium · Topics: cdc, deduplication, merge-logic · Asked at: Databricks, Confluent, Netflix, Stripe

Problem

orders_cdc is a Debezium-style change log: op is c (insert), u (update) or d (delete); lsn is the log sequence number (commit order). Events can arrive out of order (ingested_at order is not lsn order) and can be duplicated. Return the current state of the orders table: order_id, status, amount for orders that are not deleted, ordered by order_id.

Schema and sample data

CREATE TABLE orders_cdc (order_id INTEGER, op TEXT, status TEXT, amount INTEGER, lsn INTEGER, ingested_at TEXT);
INSERT INTO orders_cdc VALUES
(1,'c','NEW',100,10,'2026-01-01 10:00'),
(1,'u','PAID',100,15,'2026-01-01 10:05'),
(2,'c','NEW',50,11,'2026-01-01 10:01'),
(1,'u','SHIPPED',100,22,'2026-01-01 10:09'),
(1,'u','PAID',100,15,'2026-01-01 10:10'),
(3,'c','NEW',75,12,'2026-01-01 10:02'),
(3,'d',NULL,NULL,30,'2026-01-01 10:11'),
(2,'u','PAID',55,25,'2026-01-01 10:12'),
(4,'u','PAID',20,41,'2026-01-01 10:20'),
(4,'c','NEW',20,40,'2026-01-01 10:21');

Expected output

order_idstatusamount
1SHIPPED100
2PAID55
4PAID20

Hints

Hint 1

The latest change per key wins, where “latest” means highest lsn, not latest ingestion.

Hint 2

If the latest change is a delete, the row must not appear.

Solution

WITH latest AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY lsn DESC) AS rn
  FROM orders_cdc
)
SELECT order_id, status, amount
FROM latest
WHERE rn = 1 AND op <> 'd'
ORDER BY order_id;

Explanation

This is exactly the logic inside MERGE ... WHEN MATCHED AND s.lsn > t.lsn and DLT APPLY CHANGES ... SEQUENCE BY lsn.

Follow-up questions

Write the MERGE that applies one micro-batch of these events to a Delta table.

MERGE INTO silver.orders t USING (latest-per-key from batch) s ON t.order_id = s.order_id WHEN MATCHED AND s.lsn > t.lsn AND s.op = 'd' THEN DELETE WHEN MATCHED AND s.lsn > t.lsn THEN UPDATE SET * WHEN NOT MATCHED AND s.op <> 'd' THEN INSERT *.

How would you build SCD2 history from the same log?

Keep all non-duplicate events per key ordered by lsn; valid_from = event time, valid_to = LEAD(event time); a delete closes the last version.