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
The orders fact is enriched with customer attributes before it is published. Last month the published table had more rows than the source and revenue was overstated by eleven percent, because the customer dimension had picked up a second row for some customers and every one of their orders matched twice.
Write join_feeds(left, right, key, how). Return the joined rows and the stats that would have caught it.
Function to write
join_feeds(left: list[dict], right: list[dict], key: str, how: str) -> dictA dict with rows — the joined output in left order — and stats describing the row-count change.
How to approach it
Index the right side into a dict of lists first, then one pass over the left side.
Sample cases
+ 2 held back until you submit
a dimension with two rows per key
One key matches twice so the row count grows, and one order matches nothing at all.
Input
Argument 1
| order_id | customer_id | amount |
|---|---|---|
| o1 | c1 | 100 |
| o2 | c2 | 50 |
| o3 | c9 | 25 |
| o4 | c1 | 10 |
Argument 2
| customer_id | name | tier |
|---|---|---|
| c1 | Ada | gold |
| c2 | Grace | silver |
| c1 | Ada Lovelace | platinum |
Argument 3
'customer_id'Argument 4
'inner'Returns
{
'rows': [
{
'order_id': 'o1',
'customer_id': 'c1',
'amount': 100,
'name': 'Ada',
'tier': 'gold'
},
{
'order_id': 'o1',
'customer_id': 'c1',
'amount': 100,
'name': 'Ada Lovelace',
'tier': 'platinum'
},
{
'order_id': 'o2',
'customer_id': 'c2',
'amount': 50,
'name': 'Grace',
'tier': 'silver'
},
{
'order_id': 'o4',
'customer_id': 'c1',
'amount': 10,
'name': 'Ada',
'tier': 'gold'
},
{
'order_id': 'o4',
'customer_id': 'c1',
'amount': 10,
'name': 'Ada Lovelace',
'tier': 'platinum'
}
],
'stats': {
'left_rows': 4,
'output_rows': 5,
'unmatched_left': 1,
'fanned_out_keys': [
'c1'
]
}
}the same join, keeping every order
A left join keeps the unmatched order, so the output is one row longer than the inner join.
Input
Argument 1
| order_id | customer_id | amount |
|---|---|---|
| o1 | c1 | 100 |
| o2 | c2 | 50 |
| o3 | c9 | 25 |
| o4 | c1 | 10 |
Argument 2
| customer_id | name | tier |
|---|---|---|
| c1 | Ada | gold |
| c2 | Grace | silver |
| c1 | Ada Lovelace | platinum |
Argument 3
'customer_id'Argument 4
'left'Returns
{
'rows': [
{
'order_id': 'o1',
'customer_id': 'c1',
'amount': 100,
'name': 'Ada',
'tier': 'gold'
},
{
'order_id': 'o1',
'customer_id': 'c1',
'amount': 100,
'name': 'Ada Lovelace',
'tier': 'platinum'
},
{
'order_id': 'o2',
'customer_id': 'c2',
'amount': 50,
'name': 'Grace',
'tier': 'silver'
},
{
'order_id': 'o3',
'customer_id': 'c9',
'amount': 25
},
{
'order_id': 'o4',
'customer_id': 'c1',
'amount': 10,
'name': 'Ada',
'tier': 'gold'
},
{
'order_id': 'o4',
'customer_id': 'c1',
'amount': 10,
'name': 'Ada Lovelace',
'tier': 'platinum'
}
],
'stats': {
'left_rows': 4,
'output_rows': 6,
'unmatched_left': 1,
'fanned_out_keys': [
'c1'
]
}
}no orders
An empty left side produces no rows and no fan-out, whatever the right side holds.
Input
Argument 1
[] (empty list)
Argument 2
| customer_id | name | tier |
|---|---|---|
| c1 | Ada | gold |
| c2 | Grace | silver |
| c1 | Ada Lovelace | platinum |
Argument 3
'customer_id'Argument 4
'left'Returns
{
'rows': [],
'stats': {
'left_rows': 0,
'output_rows': 0,
'unmatched_left': 0,
'fanned_out_keys': []
}
}Constraints
key. Emit one output row per matching right row — a left row matching twice produces two output rows. That is what a join does, and hiding it is what caused the incident.how is inner or left. An inner join drops a left row with no match; a left join keeps it, carrying only its own fields.<field>_right. Never overwrite the left value.left_rows, output_rows, unmatched_left and fanned_out_keys — the sorted keys that matched more than one right row.unmatched_left counts left rows with no match, in both join modes.Worked example
Customer c1 appears twice in the dimension, as Ada and as Ada Lovelace. Orders o1 and o4 both belong to c1, so each matches twice and the inner join turns four orders into five rows — with o1 counted twice at 100.0. The stats say output_rows is 5 against left_rows of 4, and fanned_out_keys names c1.
That is the whole point of the exercise. The join is not wrong: it is doing exactly what a join does with a dimension that has two rows for one key. What was missing was any signal that the row count had changed, which is why the arithmetic downstream was wrong for a month before anybody noticed.
What this tests
Indexing one side before the loop instead of scanning it inside, and understanding fan-out as a property of the data rather than a bug in the code. The measurement matters more than the join — anyone can write the join.
join_feeds(left: list[dict], right: list[dict], key: str, how: str) -> dictSubmit 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.