Financial Ledger Running Balance with Duplicate Timestamps
1. Analytical Significance & What It Means
Scenario & Frontier TrapTests window frame boundary specification (ROWS vs default RANGE) on duplicate timestamp ordering.
In ANSI SQL and DuckDB, `SUM(...) OVER (ORDER BY col)` defaults to `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW` rather than `ROWS`. When two rows have identical ordering keys (same entry_time), RANGE treats them as equal peers and includes BOTH rows in the aggregate for the first row, prematurely applying the peer sum ($80.00 instead of $50.00). Strict cumulative calculations require explicit `ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW` and tie-breaker sorting.
Calculate the sequential running balance after each ledger transaction for each account in `ledger_entries`. Note that multiple ledger entries can occur at the exact same timestamp. Each transaction must be accumulated strictly entry-by-entry based on entry_id ordering, avoiding premature peer grouping. Required output columns: - entry_id (INT) - account_id (INT) - entry_time (TIMESTAMP) - amount (DECIMAL) - running_balance (DECIMAL): Cumulative sum of amount for the account up to and including this entry Sort the results by account_id ASC, entry_id ASC.
2. Underlying Tables, Row Counts & Data Volume
1 Tables (1,000,000 rows • 30.5 MiB)Production-scale fixtures loaded into the isolated DuckDB sandbox with at least 1,000,000 records per table:
entry_id (INTEGER) account_id (INTEGER) entry_time (TIMESTAMP) amount (DECIMAL(10,2))| # | entry_id | account_id | entry_time | amount |
|---|---|---|---|---|
| 1 | 1 | 100 | 2025-01-01 10:00:00 | 50 |
| 2 | 2 | 100 | 2025-01-01 10:00:00 | 30 |
| 3 | 3 | 100 | 2025-01-01 10:15:00 | -20 |
| 4 | 4 | 200 | 2025-01-01 12:00:00 | 100 |
| 5 | 4 | 200 | 2026-03-01 09:30:00.000005 | 10.13 |
| 6 | 5 | 201 | 2026-03-01 09:30:00.000029 | 0.01 |
| 7 | 6 | 202 | 2026-03-01 09:30:00.000042 | 30.3 |
| 8 | 7 | 203 | 2026-03-01 09:30:00.000072 | 116.54 |
| 9 | 8 | 204 | 2026-03-01 09:30:00.000090 | 100.7 |
| 10 | 9 | 205 | 2026-03-01 09:30:00.000113 | 0.01 |
| 11 | 10 | 206 | 2026-03-01 09:30:00.000134 | 129 |
| 12 | 11 | 207 | 2026-03-01 09:30:00.000141 | 49.24 |
| 13 | 12 | 208 | 2026-03-01 09:30:00.000172 | 0.01 |
| 14 | 13 | 209 | 2026-03-01 09:30:00.000182 | 28.84 |
| 15 | 14 | 210 | 2026-03-01 09:30:00.000202 | 51.36 |
3. Graphical Query Execution Plan & Cost Bottlenecks
Physical Operator Tree (DuckDB 2.0 Profiler)Visual flowchart of the physical execution pipeline. Operators with high relative costs (≥ 20% of query runtime or heavy latency) are visually highlighted:
| Operator | Cost % | Latency | Processed Rows | Data Volume | Details / Table | Status |
|---|---|---|---|---|---|---|
| WINDOW | 71.4% | 279.90 ms | 1,000,000 | 38.15 MB | Projections: sum_no_overflow(amount) OVER (PARTI | 🔥 BOTTLENECK |
| ORDER_BY | 28.0% | 109.61 ms | 1,000,000 | 38.15 MB | - | 🔥 BOTTLENECK |
| TABLE_SCAN | 0.6% | 2.17 ms | 1,000,000 | 22.89 MB | memory.main.ledger_entries | Normal |
| PROJECTION | 0.1% | 0.27 ms | 1,000,000 | 38.15 MB | Projections: ['#0', '#1', '#2', '#3', '#4'] | Normal |
4. Queries Executed (Candidate vs Golden Ground Truth)
Beautified & Syntax HighlightedSELECT entry_id,
account_id,
entry_time,
amount,
sum(amount) OVER (PARTITION BY account_id
ORDER BY entry_time, entry_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_balance
FROM ledger_entries
ORDER BY account_id ASC,
entry_id ASC;
SELECT entry_id,
account_id,
entry_time,
amount,
sum(amount) OVER (PARTITION BY account_id
ORDER BY entry_time, entry_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_balance
FROM ledger_entries
ORDER BY account_id ASC,
entry_id ASC;
CREATE TABLE ledger_entries (entry_id INT, account_id INT, entry_time TIMESTAMP, amount decimal(10, 2));
-- Multiple entries at exact same second for account 100
INSERT INTO ledger_entries
VALUES (1, 100, '2025-01-01 10:00:00', 50.00),
(2, 100, '2025-01-01 10:00:00', 30.00),
(3, 100, '2025-01-01 10:15:00', -20.00),
(4, 200, '2025-01-01 12:00:00', 100.00);
5. Query Results & Expected Ground Truth
Tabular Comparison| # | entry_id | account_id | entry_time | amount | running_balance |
|---|---|---|---|---|---|
| 1 | 1 | 100 | 2025-01-01 10:00:00 | 50 | 50 |
| 2 | 2 | 100 | 2025-01-01 10:00:00 | 30 | 80 |
| 3 | 3 | 100 | 2025-01-01 10:15:00 | -20 | 60 |
| 4 | 4 | 200 | 2025-01-01 12:00:00 | 100 | 100 |
| 5 | 4 | 200 | 2026-03-01 09:30:00.000005 | 10.13 | 110.13 |
| 6 | 5 | 201 | 2026-03-01 09:30:00.000029 | 0.01 | 0.01 |
| 7 | 6 | 202 | 2026-03-01 09:30:00.000042 | 30.3 | 30.3 |
| 8 | 7 | 203 | 2026-03-01 09:30:00.000072 | 116.54 | 116.54 |
| 9 | 8 | 204 | 2026-03-01 09:30:00.000090 | 100.7 | 100.7 |
| 10 | 9 | 205 | 2026-03-01 09:30:00.000113 | 0.01 | 0.01 |
| 11 | 10 | 206 | 2026-03-01 09:30:00.000134 | 129 | 129 |
| 12 | 11 | 207 | 2026-03-01 09:30:00.000141 | 49.24 | 49.24 |
| 13 | 12 | 208 | 2026-03-01 09:30:00.000172 | 0.01 | 0.01 |
| 14 | 13 | 209 | 2026-03-01 09:30:00.000182 | 28.84 | 28.84 |
| 15 | 14 | 210 | 2026-03-01 09:30:00.000202 | 51.36 | 51.36 |
| 16 | 15 | 211 | 2026-03-01 09:30:00.000223 | 21.13 | 21.13 |
| 17 | 16 | 212 | 2026-03-01 09:30:00.000252 | 0.01 | 0.01 |
| 18 | 17 | 213 | 2026-03-01 09:30:00.000262 | 30.58 | 30.58 |
| 19 | 18 | 214 | 2026-03-01 09:30:00.000280 | 39.29 | 39.29 |
| 20 | 19 | 215 | 2026-03-01 09:30:00.000311 | 0.01 | 0.01 |
| 21 | 20 | 216 | 2026-03-01 09:30:00.000321 | 44.13 | 44.13 |
| 22 | 21 | 217 | 2026-03-01 09:30:00.000341 | 47.45 | 47.45 |
| 23 | 22 | 218 | 2026-03-01 09:30:00.000361 | 46.79 | 46.79 |
| 24 | 23 | 219 | 2026-03-01 09:30:00.000391 | 0.01 | 0.01 |
| 25 | 24 | 220 | 2026-03-01 09:30:00.000408 | 0.01 | 0.01 |
| # | entry_id | account_id | entry_time | amount | running_balance |
|---|---|---|---|---|---|
| 1 | 1 | 100 | 2025-01-01 10:00:00 | 50 | 50 |
| 2 | 2 | 100 | 2025-01-01 10:00:00 | 30 | 80 |
| 3 | 3 | 100 | 2025-01-01 10:15:00 | -20 | 60 |
| 4 | 4 | 200 | 2025-01-01 12:00:00 | 100 | 100 |
| 5 | 4 | 200 | 2026-03-01 09:30:00.000005 | 10.13 | 110.13 |
| 6 | 5 | 201 | 2026-03-01 09:30:00.000029 | 0.01 | 0.01 |
| 7 | 6 | 202 | 2026-03-01 09:30:00.000042 | 30.3 | 30.3 |
| 8 | 7 | 203 | 2026-03-01 09:30:00.000072 | 116.54 | 116.54 |
| 9 | 8 | 204 | 2026-03-01 09:30:00.000090 | 100.7 | 100.7 |
| 10 | 9 | 205 | 2026-03-01 09:30:00.000113 | 0.01 | 0.01 |
| 11 | 10 | 206 | 2026-03-01 09:30:00.000134 | 129 | 129 |
| 12 | 11 | 207 | 2026-03-01 09:30:00.000141 | 49.24 | 49.24 |
| 13 | 12 | 208 | 2026-03-01 09:30:00.000172 | 0.01 | 0.01 |
| 14 | 13 | 209 | 2026-03-01 09:30:00.000182 | 28.84 | 28.84 |
| 15 | 14 | 210 | 2026-03-01 09:30:00.000202 | 51.36 | 51.36 |
| 16 | 15 | 211 | 2026-03-01 09:30:00.000223 | 21.13 | 21.13 |
| 17 | 16 | 212 | 2026-03-01 09:30:00.000252 | 0.01 | 0.01 |
| 18 | 17 | 213 | 2026-03-01 09:30:00.000262 | 30.58 | 30.58 |
| 19 | 18 | 214 | 2026-03-01 09:30:00.000280 | 39.29 | 39.29 |
| 20 | 19 | 215 | 2026-03-01 09:30:00.000311 | 0.01 | 0.01 |
| 21 | 20 | 216 | 2026-03-01 09:30:00.000321 | 44.13 | 44.13 |
| 22 | 21 | 217 | 2026-03-01 09:30:00.000341 | 47.45 | 47.45 |
| 23 | 22 | 218 | 2026-03-01 09:30:00.000361 | 46.79 | 46.79 |
| 24 | 23 | 219 | 2026-03-01 09:30:00.000391 | 0.01 | 0.01 |
| 25 | 24 | 220 | 2026-03-01 09:30:00.000408 | 0.01 | 0.01 |