SQL Quest

Lessons, hints, explained solutions, the in-browser PostgreSQL editor and practice answer checks in your browser are available. Graded assessments, recorded progress from answer checks and new certificates aren't available yet.

Wadi Market analytics mart

Wadi Market (fictional) · 7 tables · 65,785 rows · version 1

Open in the playground

A business-intelligence star schema: a date dimension with Saudi weekends, fiscal years and retail seasons, customer, product and channel dimensions, and three fact tables (order lines, web/app sessions and monthly marketing spend). The customer dimension keeps history (a slowly changing dimension), so a customer who moved city has two rows. Ideal for GROUP BY reporting, ROLLUP/CUBE, window functions, period-over-period comparisons and funnel analysis. Amounts are in SAR. The mart is simulated separately from the Wadi Market operational database, so its totals do not reconcile with the shop dataset.

The documentation is open to everyone. Querying this dataset in the playground is included with Formula Quest membership; lessons that use it follow their own access.

Relationships

dim_date1,096PKdate_keyfull_dateyearquartermonthmonth_namemonth_startiso_weekday_of_month+ 9 more columnsdim_customer1,040PKcustomer_keycustomer_idfull_namesegmentcityregionsignup_datevalid_fromvalid_to+ 1 more columnsdim_product61PKproduct_keyproduct_idskuproduct_namecategorysubcategorybrandlist_priceis_discontinueddim_channel4PKchannel_keychannel_namechannel_typehas_session_trackinglaunched_onfact_sales25,153PKorder_idPKline_noFKdate_keyFKcustomer_keyFKproduct_keyFKchannel_keyquantitygross_amountdiscount_amount+ 3 more columnsfact_web_sessions38,164PKsession_idFKdate_keyFKchannel_keyFKcustomer_keydevicetraffic_sourcereached_product_pageadded_to_cartstarted_checkout+ 2 more columnsfact_marketing_spend267PKspend_idFKmonth_keyFKchannel_keycampaign_typespend_amountbudget_amount
Arrows point from a foreign key to the table it references. PK = primary key, FK = foreign key. Numbers are row counts.

Sample queries

Net sales by month
SELECT d.year, d.month, d.month_name,
       sum(f.net_amount) AS net_sales
FROM fact_sales AS f
JOIN dim_date AS d ON d.date_key = f.date_key
GROUP BY d.year, d.month, d.month_name
ORDER BY d.year, d.month;
Margin by category
SELECT p.category,
       sum(f.net_amount) AS net_sales,
       sum(f.net_amount - f.cost_amount) AS gross_margin
FROM fact_sales AS f
JOIN dim_product AS p ON p.product_key = f.product_key
GROUP BY p.category
ORDER BY net_sales DESC;
Sales by region at the time of sale
SELECT c.region, d.year, sum(f.net_amount) AS net_sales
FROM fact_sales AS f
JOIN dim_customer AS c ON c.customer_key = f.customer_key
JOIN dim_date AS d ON d.date_key = f.date_key
WHERE c.customer_key <> 0
GROUP BY c.region, d.year
ORDER BY c.region, d.year;
Conversion funnel by channel
SELECT ch.channel_name,
       count(*) AS sessions,
       avg(s.reached_product_page::int) AS product_page_rate,
       avg(s.added_to_cart::int) AS cart_rate,
       avg(s.purchased::int) AS conversion_rate
FROM fact_web_sessions AS s
JOIN dim_channel AS ch ON ch.channel_key = s.channel_key
GROUP BY ch.channel_name;
Marketing spend vs budget by quarter
SELECT d.year, d.quarter,
       sum(m.spend_amount) AS spend,
       sum(m.budget_amount) AS budget
FROM fact_marketing_spend AS m
JOIN dim_date AS d ON d.date_key = m.month_key
GROUP BY d.year, d.quarter
ORDER BY d.year, d.quarter;

Data dictionary

dim_date

1,096 rows · primary key (date_key)

Calendar dimension: one row per day from 2023-01-01 to 2025-12-31, with Saudi weekends, fiscal periods and retail seasons.

ColumnTypeNull?KeyDescription
date_keyintegerno PKDate as a number in YYYYMMDD form, e.g. 20250314. Used as the foreign key in fact tables.
full_datedatenouniqueThe calendar date.
yearsmallintnoCalendar year.
quartersmallintnoCalendar quarter (1–4).
monthsmallintnoMonth number (1–12).
month_nametextnoMonth name in English, e.g. March.
month_startdatenoFirst day of the month (handy for monthly grouping and for joining monthly facts).
iso_weeksmallintnoISO week number (weeks start on Monday; early January can belong to the previous year's last week).
day_of_monthsmallintnoDay of the month (1–31).
day_of_weeksmallintnoDay of the week, 1 = Sunday … 7 = Saturday (the Saudi working week starts on Sunday).
day_nametextnoDay name in English, e.g. Friday.
is_weekendbooleannoTRUE on Friday and Saturday (the weekend in Saudi Arabia).
fiscal_yearsmallintnoWadi Market's fiscal year, which runs 1 April – 31 March and is named after the year it ends in.
fiscal_quartersmallintnoFiscal quarter (Q1 = April–June).
seasontextnoRetail season: Ramadan, Eid al-Fitr, Eid al-Adha, White Friday, National Day, Founding Day, Summer or Regular.
is_ramadanbooleannoTRUE during the month of Ramadan.
is_holidaybooleannoTRUE on Saudi public holidays (Founding Day, Eid holidays, National Day).
holiday_nametextyesName of the public holiday. NULL on ordinary days.

dim_customer

1,040 rows · primary key (customer_key)

Customer dimension with history (slowly changing dimension type 2): a new row is added when a customer moves city. customer_key 0 is the 'Guest checkout' member for orders without an account.

ColumnTypeNull?KeyDescription
customer_keyintegerno PKSurrogate key for one version of a customer. Fact tables join on this. 0 = Guest checkout.
customer_idintegeryesBusiness (natural) key from the operational system; the same for every version of a customer. NULL for the guest member.
full_nametextnoCustomer's name.
segmenttextnoconsumer, business, or guest (the Guest checkout member).
citytextyesCity the customer lived in while this version was valid. NULL for the guest member.
regiontextyesRegion of that city (Central, Eastern, Western, Northern, Southern). NULL for the guest member.
signup_datedateyesDate the customer first registered (same on every version). NULL for the guest member.
valid_fromdatenoFirst day this version was valid.
valid_todatenoLast day this version was valid; 9999-12-31 for the current version.
is_currentbooleannoTRUE for the customer's current version.

dim_product

61 rows · primary key (product_key)

Product dimension, flattened: each product carries its department (category) and lowest-level category (subcategory).

ColumnTypeNull?KeyDescription
product_keyintegerno PKSurrogate key (starts at 1001). Fact tables join on this.
product_idintegernouniqueNatural key from the operational system.
skutextnouniqueStock-keeping unit code, e.g. WM-ELE-1001.
product_nametextnoProduct name.
categorytextnoTop-level department, e.g. Electronics.
subcategorytextnoLowest-level category, e.g. Headphones.
brandtextnoBrand name; 'Unbranded' when the product has no brand.
list_pricenumeric(12,2)noCurrent list price in SAR.
is_discontinuedbooleannoTRUE if the product is no longer sold.

dim_channel

4 rows · primary key (channel_key)

Sales channels.

ColumnTypeNull?KeyDescription
channel_keyintegerno PKSurrogate key for the channel.
channel_nametextnouniqueWeb, App, Marketplace or Social Commerce.
channel_typetextnoowned (our own website/app/social shop) or partner (a third-party marketplace).
has_session_trackingbooleannoTRUE if sessions on this channel are recorded in fact_web_sessions.
launched_ondatenoDate the channel started selling.

fact_sales

25,153 rows · primary key (order_id, line_no)

Sales fact table. Grain: one order line (one product in one order). Cancelled orders are not loaded.

ColumnTypeNull?KeyDescription
order_idintegerno PKOrder number (a degenerate dimension: there is no order dimension table).
line_nosmallintno PKLine number within the order.
date_keyintegerno dim_date.date_keyOrder date (YYYYMMDD).
customer_keyintegerno dim_customer.customer_keyCustomer version valid on the order date; 0 = Guest checkout.
product_keyintegerno dim_product.product_keyProduct sold.
channel_keyintegerno dim_channel.channel_keyChannel the order came through.
quantityintegernoUnits sold.
gross_amountnumeric(12,2)noQuantity × list price at the time, in SAR, before discounts.
discount_amountnumeric(12,2)noPromotional discount on the line in SAR.
net_amountnumeric(12,2)nogross_amount − discount_amount: the revenue for the line in SAR.
cost_amountnumeric(12,2)yesCost of the goods sold on this line in SAR. NULL when the product's cost was not recorded.
is_returnedbooleannoTRUE if the line was later returned and refunded.

fact_web_sessions

38,164 rows · primary key (session_id)

Website, app and social-shop sessions with funnel flags. Grain: one visit. Marketplace orders happen on the partner's site and have no sessions here. Funnel steps are cumulative.

ColumnTypeNull?KeyDescription
session_idbigintno PKUnique session number.
date_keyintegerno dim_date.date_keyDay the session started (YYYYMMDD).
channel_keyintegerno dim_channel.channel_keyWeb, App or Social Commerce.
customer_keyintegeryes dim_customer.customer_keyLogged-in customer version. NULL for anonymous visitors.
devicetextnomobile, desktop or tablet.
traffic_sourcetextnoHow the visitor arrived: organic, direct, paid_search, social, email or referral.
reached_product_pagebooleannoTRUE if the visitor viewed at least one product page.
added_to_cartbooleannoTRUE if something was added to the cart.
started_checkoutbooleannoTRUE if the visitor started checkout.
purchasedbooleannoTRUE if the session ended in an order.
order_idintegeryesThe order placed in this session (matches fact_sales.order_id). NULL when nothing was bought.

fact_marketing_spend

267 rows · primary key (spend_id)

Monthly marketing spend and budget. Grain: one month × channel × campaign type. Months without activity have no row.

ColumnTypeNull?KeyDescription
spend_idintegerno PKUnique row number.
month_keyintegerno dim_date.date_keyFirst day of the month the spend covers (YYYYMMDD, e.g. 20250301).
channel_keyintegerno dim_channel.channel_keyChannel the campaign promoted.
campaign_typetextnopaid_search, display, email, influencer, app_install, paid_social or sponsored_listings.
spend_amountnumeric(12,2)noActual spend in SAR.
budget_amountnumeric(12,2)noPlanned budget in SAR.