Submission: dbt Project
Wolt Snack Store — Berlin 2023
dbt project overview

The wolt_analytics dbt project transforms three raw CSV sources into a star-schema dimensional model that powers this platform. Task 1 focused on modeling — the 8 business questions in the brief are design guides, not questions to answer directly. The model is built so the Analytics Team can answer each with a simple SELECT … GROUP BY against mart tables, without JSON parsing or heavy joins at query time.

4 staging models 2 intermediate models 7 mart models 2 analysis files
Layer architecture & reasoning
1. Staging — parse, clean, and standardise raw data
  • stg_item_logs — Parses nested JSON payloads, deduplicates conflicting log_item_id rows (keeping valid positive prices), forward-fills null prices, and prepares SCD Type 2 inputs.
    Why: source item logs contain corrections and null prices that would break point-in-time revenue if used raw.
  • stg_purchase_items — Explodes purchase baskets to one row per item per order.
    Why: category and product analysis requires line-item grain.
  • stg_purchase_logs / stg_promos — Cleans types, keys, and promo windows.
    Why: downstream joins and date logic need consistent, typed columns.
2. Intermediate — business logic & historisation
  • int_items_scd — Builds SCD Type 2 validity windows (valid_from / valid_to) for every item attribute change.
    Why: item prices and names change over time; orders must join to the price that was active when the order was placed.
  • int_purchase_items_enriched — Point-in-time item join + promo matching at order timestamp.
    Why: centralises the hardest join logic once, so marts stay simple.
3. Marts — analytics-ready star schema
  • fct_purchases (order grain) — Pre-computes fee ratios, distance buckets, promo flags, and first-purchase indicators.
    Why: delivery, fee, and promo-order questions should not require re-aggregation from line items.
  • fct_purchase_items (line-item grain) — Carries point-in-time price, discount, and net value.
    Why: category/product revenue and promo volume analysis.
  • dim_customers — Derives lifetime value, tenure, and behavioural segments (one-time → power user).
    Why: retention analysis should not recompute customer stats in every query.
  • dim_items / dim_items_history / dim_promotions / dim_dates — Conformed dimensions for flexible slicing by product, promo, and time period.
Key design decisions
DecisionReasoning
Star schema, two fact grains Orders and order-lines answer different questions. Splitting facts avoids fan-out when aggregating order-level metrics (fees, distance) alongside item-level metrics (category revenue).
SCD Type 2 for items Prices change mid-year. Using current prices would misstate historical revenue; validity windows give accurate point-in-time joins.
Pre-computed segments & buckets Customer segments and distance buckets are derived once in the model so dashboard and ad-hoc queries stay fast and consistent.
Promo end date exclusive Matches the brief: the end date is the first day the discount no longer applies.
DuckDB locally, Snowflake-portable SQL No warehouse required for the assignment; SQL patterns (CTEs, window functions) transfer to Snowflake with minimal changes.
How to run locally

The downloadable ZIP is self-contained for evaluators: dbt project + DuckDB + raw CSVs + a short README. After unzipping the package:

# optional but recommended
python3 -m venv .venv && source .venv/bin/activate

pip install -r requirements-dbt.txt
cd wolt_analytics
dbt run
dbt test

Optional: rebuild DuckDB from the included CSVs with python3 load_raw_data.py at the package root. Validation queries in analyses/business_questions.sql show that all 8 Task 1 business questions are answerable from the marts.

Download / upload project ZIP
Download dbt Project (ZIP) Includes wolt_analytics/, wolt_snack_store.duckdb, raw CSVs, and run instructions (excludes dbt target/ and logs/).

Upload a ZIP of the full evaluator package if you want to pin a specific archive. Once uploaded, the download button moves to the top of this page.