Sample dataset · CC0
A lookup table, built to be looked up.
Nine columns of catalog: a text primary key, a name, a category, what it costs, what it sells for, the margin between them, how many are on the shelf, how it is rated and whether it is still sold.
9 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
The 100-row file is the useful one here. It already covers every SKU the orders and inventory datasets reference, so you never need the 1,000-row version to make a join work.
| Format | Small | Standard |
|---|---|---|
| CSV | 100 rows (7.0 KB) | 1,000 rows (68.6 KB) |
| JSON | 100 rows (17.4 KB) | 1,000 rows (173.4 KB) |
| JSONL | 100 rows (17.1 KB) | 1,000 rows (170.5 KB) |
| Excel | 100 rows (21.1 KB) | 1,000 rows (129.1 KB) |
| Parquet | 100 rows (5.0 KB) | 1,000 rows (25.3 KB) |
Bigger catalogs, built here
Larger sizes extend the catalog past SKU-1100 with new products. Orders and inventory keep pointing only at the first 60, so the extra rows are the unsold long tail, which is a realistic thing for a catalog to have.
The first eight rows
The first eight rows of the 1,000-row file. Price is always above unit_cost, so margin is never negative.
| sku | product_name | category | unit_cost | price | margin_pct | stock | rating | discontinued |
|---|---|---|---|---|---|---|---|---|
| SKU-1001 | Wireless Mouse Max | Audio | 106.47 | 221.10 | 51.8 | 320 | 3.9 | false |
| SKU-1002 | Mechanical Keyboard Classic | Office | 109.19 | 187.97 | 41.9 | 144 | 3.9 | false |
| SKU-1003 | USB-C Hub Max | Electronics | 198.25 | 365.32 | 45.7 | 53 | 3.5 | true |
| SKU-1004 | Laptop Stand Max | Accessories | 204.42 | 349.87 | 41.6 | 95 | 4.4 | false |
| SKU-1005 | HD Webcam Classic | Home | 150.48 | 254.52 | 40.9 | 379 | 3.9 | false |
| SKU-1006 | Noise-Cancelling Headphones Lite | Audio | 35.85 | 59.75 | 40.0 | 52 | 4.0 | false |
| SKU-1007 | Portable SSD Signature | Office | 85.19 | 158.54 | 46.3 | 55 | 3.7 | true |
| SKU-1008 | 27in Monitor Signature | Electronics | 267.59 | 441.21 | 39.4 | 369 | 4.0 | false |
Nine columns, and what each one holds
| Column | Type | What it holds | Example |
|---|---|---|---|
| sku | text | Primary key in the form SKU-1001. A text key on purpose, so the join is not an integer join. | SKU-1001 |
| product_name | text | Base product plus a line name. | Wireless Mouse Max |
| category | text | One of five merchandising categories. | Audio |
| unit_cost | decimal | What the item costs to buy in, USD. | 106.47 |
| price | decimal | List price in USD. Always above unit_cost, so margin is never negative. | 221.10 |
| margin_pct | decimal | (price - unit_cost) / price as a percentage, one decimal. | 51.8 |
| stock | integer | Units on hand across all warehouses. | 320 |
| rating | decimal | Mean customer rating, 1.0 to 5.0, one decimal. | 3.9 |
| discontinued | boolean | true for roughly one SKU in twelve. | false |
What it models
A merchandising catalog: the small, slow-changing table that a large, fast-growing transaction table points at. That is the shape most people mean when they say dimension table, and it is why this file is deliberately short. A hundred rows is a realistic catalog for a small retailer and it fits on one screen, which makes it easy to check a join by eye rather than by trusting the tool.
The primary key is text, not an integer. SKU-1042 is a string, and that is the interesting part: it survives a JSON round trip, it survives Parquet, and it is the first thing to break when a tool decides to be clever about types. If your pipeline turns SKU-1042 into something else, this file will show you.
Cost, price and margin
unit_cost is always between 42 and 72 percent of price, so margin_pct sits in a plausible retail band and is never negative. It is also computed from the two columns on the same row rather than drawn separately, which means you can use this file to check whether a tool's derived column arithmetic agrees with the arithmetic already in the data.
That is a genuinely useful exercise. Add a calculated column of (price - unit_cost) / price * 100, round it to one decimal, and compare it against margin_pct. Any disagreement is a rounding policy difference in the tool, and finding out what that policy is beats reading the documentation.
The columns that are there to be awkward
discontinued is a boolean written as the strings true and false, which is the most common way a boolean arrives in a CSV and the way most importers get slightly wrong. Roughly one SKU in twelve is discontinued, so filtering on it removes a meaningful but not dominant slice.
rating is a decimal between 1.0 and 5.0 with exactly one decimal place, including values like 4.0 that a naive type sniffer will happily turn into the integer 4. stock is a plain integer that includes 0, which is a legitimate value and not a missing one, and telling those apart is the whole job of a good profiler.
What people use it for
- The lookup side of a join, small enough to verify by hand.
- Testing whether a tool preserves a text primary key like SKU-1042.
- Comparing a tool's calculated column against margin_pct, which is already correct.
- Boolean parsing, on a column written as the strings true and false.
- Category rollups, with five categories and a fixed rotation so counts are even.
What points at it
sku runs SKU-1001 upward. Orders and inventory only reference SKU-1001 to SKU-1060, so a 100-row product file already covers every order.
Two datasets treat this one as their dimension table. Orders reference it for price, and the inventory snapshot references it for unit cost, so a three-way pull gives you what you sold, what you hold and what both are worth at cost. That is the standard retail reconciliation, and it needs a catalog whose keys resolve.
Open it somewhere useful
This is a small file, which makes it the right one for trying a converter and reading the whole output.
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. Product names are assembled from a fixed pool of generic hardware and a line name, so nothing here is a real trademark or a real product.
Questions people ask about this file
Why is the 100-row file the recommended one?
Because orders and inventory only ever reference SKU-1001 through SKU-1060, and those are the first 60 rows. The 100-row catalog therefore covers every foreign key in both of those datasets with room to spare, and being short means you can scroll the whole thing and confirm a join by eye instead of trusting the tool that performed it.
Is price always above cost?
Yes. unit_cost is generated as a fraction of price between 42 and 72 percent, so margin is always positive and margin_pct always sits in a believable retail range. A catalog with occasional negative margins would be more realistic in one narrow sense and much less useful for teaching, because every chart would need a caveat.
What is margin_pct calculated from?
It is (price minus unit_cost) divided by price, times 100, rounded to one decimal place, using the values on the same row. That makes it a good target for checking your own tool: add the same calculated column, and any difference between your result and the column already in the file is a rounding policy difference worth knowing about.
Do the product names mean anything?
No. Each is a generic piece of desk hardware plus a line name such as Pro or Studio, assembled from fixed pools. Nothing here is a real product or a real trademark, which is the point: a sample catalog full of real brand names is a licensing problem waiting to be noticed by somebody's legal team.
More sample data
All twenty datasets · Messy files and every other format · Build your own schema