Ecommerce storefront

A year of orders across five joined tables, with a real Q4 peak and totals that reconcile to the cent.

An online retailer's 2025: customers, a 300-SKU catalogue, orders, line items, and reviews. Every order total is exactly the sum of its own line items, so the joins and the arithmetic both hold when you check them. Demand rises into November and December because there are more orders, not because the orders got bigger, which is how real seasonality works.

49,192 rows across 5 tables, 656 KB zipped. Public domain (CC0), no signup, no attribution required.

What is in it

customers2,000 rows

customer_id, full_name, email, city, state, country, signup_date, segment

112 signed up and never ordered

products300 rows

product_id, product_name, category, unit_price, unit_cost

every SKU name distinct

orders11,081 rows

order_id, customer_id, order_date, status, channel, order_total

order_items31,000 rows

order_item_id, order_id, product_id, quantity, unit_price, line_total

reviews4,811 rows

review_id, product_id, customer_id, rating, review_text, review_date

What holds, and how it was checked

Each line was measured against these exact files rather than asserted. The same checks ship inside the zip as INTEGRITY.txt, so you can re-run them yourself.

  • 0 orphaned foreign keys across all 5 relationships
  • 0 orders dated before their customer signed up
  • order_total equals the sum of its line items, exactly, for every order
  • 0 products priced at or below cost (margins run 22% to 64%)
  • Ratings are J-shaped (57% five-star, 7% one-star), not uniform
  • Top 10% of customers place 29.5% of orders, a realistic Pareto tail
  • 59% of prices end in .99, as real catalogues do
  • Every city belongs to its country (London and Newcastle appear under two, correctly)

Questions it can answer

  • Which category carries the best margin, and is it the one selling most?
  • How much of revenue comes from the top 10% of customers?
  • Do low-rated products actually get returned more often?
  • What does the Q4 lift look like split by channel?

Make your own version

The zip includes schema.yaml, which is this dataset's shape and runs as-is. Change a row count, add a column, rename a table: every foreign key still resolves, because referential integrity is a guarantee here rather than something the generator happens to get right.

pip install misata
misata generate --config schema.yaml --output-dir ./data
Read the docs

Other datasets

  • Retail star schema

    A dimensional model you can actually practise joins on: one fact table, four dimensions, 63,170 rows, and every join resolving.

  • Machine degradation

    100 machines monitored from commissioning to failure, with an exact remaining-useful-life label on every one of 23,118 readings.

  • B2B SaaS subscription analytics

    Accounts, seats, MRR, churn and support load, where company size actually drives the plan.