Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
Finance reconciles the payment processor against the accounting ledger every morning. stripe_charges is what the processor says it collected, stripe_ledger is what finance posted, and order_ref is the only key they share. Neither system is the master.
Return one row per exception, ordered by status then order_ref.
Result columns · in this order
order_ref | The order reference, from whichever side has it. |
charged | Amount the processor collected, NULL if absent. |
posted | Amount the ledger posted, NULL if absent. |
status | Why this reference does not reconcile. |
How to approach it
Ask which references the starter can never show you, whichever way you point the join.
Sample input
| charge_id | order_ref | amount | charged_on |
|---|---|---|---|
| ch_01 | ORD-1001 | 120 | 2026-03-01 |
| ch_02 | ORD-1002 | 89.99 | 2026-03-01 |
| ch_03 | ORD-1003 | 240 | 2026-03-02 |
| ch_04 | ORD-1004 | 45.5 | 2026-03-02 |
| ch_05 | ORD-1005 | 310 | 2026-03-03 |
| ch_06 | ORD-1006 | 75.25 | 2026-03-03 |
| ch_07 | ORD-1007 | 199 | 2026-03-04 |
| ch_08 | ORD-1008 | 60 | 2026-03-04 |
| ch_09 | ORD-1009 | 150 | 2026-03-05 |
| ch_10 | ORD-1010 | 88 | 2026-03-05 |
10 rows — all rows shown.
| entry_id | order_ref | amount | posted_on |
|---|---|---|---|
| le_01 | ORD-1001 | 120 | 2026-03-02 |
| le_02 | ORD-1002 | 89.98 | 2026-03-02 |
| le_03 | ORD-1003 | 216 | 2026-03-03 |
| le_04 | ORD-1004 | 45.5 | 2026-03-03 |
| le_05 | ORD-1006 | 75.25 | 2026-03-04 |
| le_06 | ORD-1007 | 199 | 2026-03-05 |
| le_07 | ORD-1008 | 66 | 2026-03-05 |
| le_08 | ORD-1010 | 88 | 2026-03-06 |
| le_09 | ORD-1011 | 42 | 2026-03-06 |
| le_10 | ORD-1012 | 130 | 2026-03-06 |
10 rows — all rows shown.
Expected output
| order_ref | charged | posted | status |
|---|---|---|---|
| ORD-1003 | 240 | 216 | amount_mismatch |
| ORD-1008 | 60 | 66 | amount_mismatch |
| ORD-1011 | null | 42 | missing_in_charges |
| ORD-1012 | null | 130 | missing_in_charges |
| ORD-1005 | 310 | null | missing_in_ledger |
| ORD-1009 | 150 | null | missing_in_ledger |
6 rows — all rows shown.
Constraints
status is one of 'amount_mismatch', 'missing_in_ledger' or 'missing_in_charges'.0.01 — is rounding in transit, not a break. ORD-1002 differs by exactly that and must not be reported.ORD-1011 and ORD-1012 are in the ledger and were never charged.charged and posted are NULL on whichever side has no row.status, then order_ref.Worked example
ORD-1003 was charged 240.00 and posted 216.00 — a real break of 24.00. ORD-1005 was charged 310.00 and never posted. ORD-1011 was posted 42.00 and never charged.
An inner join finds the first and neither of the others. A LEFT JOIN from the charges adds ORD-1005 and still cannot see ORD-1011 or ORD-1012, because nothing on the charge side points at them — 172.00 of unbacked ledger entries stay invisible. Comparing with c.amount <> l.amount adds the opposite error: it reports ORD-1002's one-paisa rounding as a break, and an exception report that cries wolf stops being read.
What this tests
Two-sided reconciliation: neither table is the driver, so the join has to preserve both sides, and equality on money needs a tolerance rather than an exact comparison.
Submit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.