← All SQL interview questions
Reconcile gateway payments with bank settlements
MediumJoins — Left/Right Outer JoinPayPalRazorpay
A finance team reconciles what the payment gateway recorded against what the bank actually settled. Money can be missing on either side.
Compare gateway_payments with bank_settlements on order_ref. Return only the exceptions: order_ref, gateway_amount, settled_amount and recon_status, where recon_status is:
- MISSING_SETTLEMENT when the gateway has the order but the bank does not
- UNEXPECTED_SETTLEMENT when the bank has it but the gateway does not
- AMOUNT_MISMATCH when both have it but the amounts differ
Orders that match exactly must not appear. Order by order_ref.
Sample data
Table: gateway_payments
8 row(s)
| payment_idINT | order_refTEXT | amountNUMERIC(10,2) |
|---|---|---|
| 1 | ORD-5001 | 1500.00 |
| 2 | ORD-5002 | 2300.00 |
| 3 | ORD-5003 | 899.00 |
| 4 | ORD-5004 | 4200.00 |
| 5 | ORD-5005 | 650.00 |
| 6 | ORD-5006 | 3100.00 |
| 7 | ORD-5007 | 1250.00 |
| 8 | ORD-5008 | 780.00 |
Table: bank_settlements
8 row(s)
| settlement_idINT | order_refTEXT | settled_amountNUMERIC(10,2) |
|---|---|---|
| 1 | ORD-5001 | 1500.00 |
| 2 | ORD-5002 | 2300.00 |
| 3 | ORD-5003 | 889.50 |
| 4 | ORD-5005 | 650.00 |
| 5 | ORD-5006 | 3100.00 |
| 6 | ORD-5008 | 780.00 |
| 7 | ORD-5009 | 1999.00 |
| 8 | ORD-5010 | 520.00 |
gateway_payments
- payment_idINT
- order_refTEXT
- amountNUMERIC(10,2)
bank_settlements
- settlement_idINT
- order_refTEXT
- settled_amountNUMERIC(10,2)
- Step 1: A `FULL OUTER JOIN` keeps unmatched rows from both tables, padding the missing side with NULLs.
- Step 2: `COALESCE(g.order_ref, b.order_ref)` gives one reference column regardless of which side the row came from.
- Step 3: The `WHERE` clause keeps only rows where one side is missing or the amounts differ, which drops the clean matches.
- Step 4: The `CASE` order checks the NULL sides first; a NULL amount would never satisfy `<>` on its own.
SELECT COALESCE(g.order_ref, b.order_ref) AS order_ref,
g.amount AS gateway_amount,
b.settled_amount AS settled_amount,
CASE
WHEN b.order_ref IS NULL THEN 'MISSING_SETTLEMENT'
WHEN g.order_ref IS NULL THEN 'UNEXPECTED_SETTLEMENT'
ELSE 'AMOUNT_MISMATCH'
END AS recon_status
FROM gateway_payments g
FULL OUTER JOIN bank_settlements b ON b.order_ref = g.order_ref
WHERE g.order_ref IS NULL
OR b.order_ref IS NULL
OR g.amount <> b.settled_amount
ORDER BY order_ref;More Joins — Left/Right Outer Join questions
Practising alone only goes so far — our live cohorts pair SQL depth with dashboards, agentic analytics projects and mock interviews.
Explore the program