Sample dataset · CC0
Stock levels that subtract correctly.
Ten columns of warehouse snapshot across six distribution centers and sixty SKUs. Available is always on hand minus reserved, the below-reorder flag always agrees with the numbers beside it, and unit cost matches the product catalog.
10 columns · 100 or 1,000 rows as a file · up to 1,000,000 rows generated here · CSV, JSON, JSONL, Excel, Parquet
Take a file
Take products-100.csv alongside this and inventory value reconciles across the two files, because the unit cost on a snapshot row is the catalog cost for that SKU.
| Format | Small | Standard |
|---|---|---|
| CSV | 100 rows (6.3 KB) | 1,000 rows (61.6 KB) |
| JSON | 100 rows (19.6 KB) | 1,000 rows (195.9 KB) |
| JSONL | 100 rows (19.3 KB) | 1,000 rows (193.0 KB) |
| Excel | 100 rows (21.8 KB) | 1,000 rows (143.0 KB) |
| Parquet | 100 rows (4.2 KB) | 1,000 rows (19.8 KB) |
Turn a snapshot into a history
Larger sizes add snapshot dates rather than SKUs, so a hundred thousand rows is roughly 1,600 dates across the same sixty products. That turns a snapshot into a history, which is when the interesting questions start.
The first eight rows
The first eight rows of the 1,000-row file. Sixty SKUs rotate within each snapshot date.
| snapshot_date | warehouse | sku | on_hand | reserved | available | reorder_point | below_reorder | unit_cost | days_of_cover |
|---|---|---|---|---|---|---|---|---|---|
| 2026-01-01 | DC-Dallas | SKU-1001 | 865 | 46 | 819 | 100 | false | 151.81 | 50.6 |
| 2026-01-01 | DC-Atlanta | SKU-1002 | 1060 | 448 | 612 | 309 | false | 95.07 | 87.4 |
| 2026-01-01 | DC-Atlanta | SKU-1003 | 262 | 77 | 185 | 49 | false | 232.81 | 14.5 |
| 2026-01-01 | DC-Dallas | SKU-1004 | 685 | 335 | 350 | 314 | false | 152.04 | 9.9 |
| 2026-01-01 | DC-Atlanta | SKU-1005 | 268 | 8 | 260 | 66 | false | 136.51 | 76.5 |
| 2026-01-01 | DC-Reno | SKU-1006 | 795 | 87 | 708 | 80 | false | 39.76 | 43.4 |
| 2026-01-01 | DC-Dallas | SKU-1007 | 26 | 13 | 13 | 288 | true | 84.40 | 0.5 |
| 2026-01-01 | DC-Dallas | SKU-1008 | 1125 | 279 | 846 | 142 | false | 258.74 | 31.3 |
Ten columns, and what each one holds
| Column | Type | What it holds | Example |
|---|---|---|---|
| snapshot_date | date | The day this count was taken. One block of rows per date. | 2026-01-01 |
| warehouse | text | One of six distribution centres. | DC-Dallas |
| sku | text | Foreign key into products, SKU-1001 to SKU-1060. | SKU-1001 |
| on_hand | integer | Units physically in the building. | 865 |
| reserved | integer | Units already promised to orders. Never above on_hand. | 46 |
| available | integer | on_hand minus reserved. Checked on every row. | 819 |
| reorder_point | integer | The level that triggers a purchase order. | 100 |
| below_reorder | boolean | true when available is under reorder_point. Roughly one row in five. | false |
| unit_cost | decimal | Cost per unit in USD, matching the products catalogue for that SKU. | 151.81 |
| days_of_cover | decimal | available divided by the SKU's mean daily demand, one decimal. | 50.6 |
What it models
A stock position: for a given date, warehouse and SKU, how many units are in the building, how many are already promised, how many are actually sellable, and whether that number has fallen below the level that triggers a purchase order. It is the file that sits behind every out-of-stock alert.
Snapshot dates advance in blocks of sixty rows, one per SKU, so the 1,000-row file covers about seventeen dates. Warehouse is drawn per row rather than fixed per block, which is a simplification worth knowing about: this is a sample of positions rather than a complete count of every site on every date.
The arithmetic, and the flag
available is on_hand minus reserved, computed rather than drawn, and a test asserts it on every row. reserved can never exceed on_hand, so available is never negative, which spares you the conversation about whether negative stock is a data error or an oversell.
below_reorder is true exactly when available is under reorder_point. Like every other derived column in this collection, it is computed from the numbers on the same row, so the flag and the quantities cannot drift apart. That makes it a reference answer: write the rule yourself, apply it, and the two columns should match on all 1,000 rows.
days_of_cover is available divided by that SKU's mean daily demand, to one decimal. It is the column that turns a quantity into a decision, and it is also the one most likely to be infinite or undefined in real data when demand is zero. Here demand is always at least three units a day, so the column is always finite, which is a deliberate simplification rather than an accident.
Why it shares keys with the catalog
Every sku is between SKU-1001 and SKU-1060, the same space the orders dataset uses, and unit_cost is the catalog cost for that SKU. So the three files fit together: the catalog says what a thing costs and sells for, inventory says how many you hold, and orders says how many you sold.
That combination lets you build the reconciliation that most sample data cannot support. Inventory value at cost, revenue at price, units sold against units held, all from files whose keys resolve and whose prices agree. It is the difference between a demo that shows a chart and a demo that shows an answer.
What people use it for
- Inventory value calculations, joined to the product catalog for cost.
- Stockout and reorder dashboards with a flag you can verify against the quantities.
- Testing derived-column logic where the correct answer is already in the file.
- Warehouse comparison charts across six sites.
- Turning a snapshot into a time series by generating more rows.
It shares keys with the catalog
sku is SKU-1001 to SKU-1060 and unit_cost matches the products catalogue, so inventory value reconciles across the two files.
The pairing to try is inventory against the product catalog on sku. Multiply on_hand by unit_cost and sum by warehouse and you have inventory value by site, which is the number a finance team asks an operations team for and the one that is hardest to produce when the two files disagree about what a SKU costs. Here they cannot disagree.
Open it somewhere useful
Inventory value is a join and a multiply, which makes the merger and the pivot table the two tools that earn their place here.
License, and the people in it
This dataset is dedicated to the public domain under CC0 1.0. Put it in a course, a paid product, a test suite, a bug report, a screenshot, a conference talk or a book. There is nothing to ask for, nothing to sign and no attribution required. A link back is welcome and is not a condition.
There are no people in this file. Warehouses are invented distribution centers named after cities, and every quantity comes from a deterministic function rather than from a real operation.
Questions people ask about this file
Can available ever be negative?
No. reserved is generated as a fraction of on_hand, so it can never exceed it, and available is the subtraction of the two. A test checks it on every row. Real systems do produce negative available when an oversell happens, but a sample file with negative stock in it forces a caveat onto every chart built from it, so this one leaves it out.
Does the below_reorder flag ever disagree with the numbers?
It cannot, because it is computed from them: it is true exactly when available is less than reorder_point. Roughly one row in five is flagged. Write the same rule in your own tool and the results should match on all 1,000 rows, which makes the file a usable reference for testing a derived-column feature.
Does the unit cost match the product catalog?
Yes. Both files compute the cost of a SKU from the same function of the SKU, so joining inventory to products on sku and comparing the two cost columns returns no mismatches. That is what makes an inventory value reconciliation across the two files produce a single consistent number instead of two nearly-equal ones.
Is this a full snapshot of every site on every date?
No, and it is worth knowing before you draw conclusions from it. Each row picks its warehouse independently, so a given date does not carry a complete count for all six sites. Treat it as a sample of positions. If you need a complete grid, generate more rows and aggregate by warehouse and SKU rather than by date.
More sample data
All twenty datasets · Messy files and every other format · Build your own schema