SQL Tables

Course Tables β€” Beginner SQL Commands Practice | DataSosi
Beginner SQL Commands Practice Β· Course Tables Β· Reference Guide

Your Course Tables

The seven tables you will use throughout this Beginner SQL Commands Practice course β€” a complete business operations database covering users, transactions, products, orders, order items, subscriptions, and support tickets.

These are the tables you will use for this Beginner SQL Commands Practice course. Together they form a complete business operations database called sql_challenges_capstone_course, built from seven connected tables. Every SELECT, WHERE, ORDER BY, LIMIT, GROUP BY, and HAVING query in the course runs against one or more of these tables. Familiarize yourself with the field names and data types here before working through the practice exercises.
7 Tables
Users & Transactions
Orders & Products
Subscriptions & Support

What These Tables Are For

  • Practice every SQL command covered in the course β€” SELECT, WHERE, ORDER BY, LIMIT, GROUP BY, and HAVING β€” against realistic business data that mirrors what analysts work with every day
  • Answer real business questions: which users are from Canada, which transactions exceed a threshold, which products are most expensive, which orders are pending or refunded
  • Build grouped summaries across categories β€” users by country, revenue by transaction type, orders by status, subscriptions by plan tier β€” using aggregation functions on real data
  • Trace the complete business operations picture: a customer signs up (users), browses and buys (orders, order_items, products), pays over time (transactions, subscriptions), and contacts support (support_tickets)
Click any section header to open or close it

The users table stores customer profile information for the eight registered users. Each user has a first and last name, a signup date, a country, and a user_type of either Retail or Business. This table is referenced by transactions, orders, sessions, campaign_events, support_tickets, and subscriptions via user_id β€” making it the central identity table for the entire database.

Practice Queries on This Table

SELECT all users, filter by country using WHERE, sort by signup_date using ORDER BY, count users by country with GROUP BY, and show only countries with more than one user using HAVING. All six commands in the course can be practised directly against this table.

user_idfirst_namelast_namesignup_datecountryuser_type
1AvaBrown2024-01-05CanadaRetail
2LiamWilson2024-01-12CanadaBusiness
3MayaSingh2024-02-03United StatesRetail
4NoahChen2024-02-18CanadaRetail
5SophiaMartin2024-03-07United KingdomBusiness
6EthanDavis2024-03-25CanadaRetail
7IsabellaGarcia2024-04-02United StatesBusiness
8LucasTaylor2024-04-15CanadaRetail
Column Breakdown
Column NameData TypeConstraintsExplanation
user_idINTPRIMARY KEYUnique identifier (1–8). Referenced as a foreign key by all other tables.
first_nameVARCHAR(50)NoneCustomer first name. Used in LIKE pattern filtering (e.g. first_name LIKE β€˜A%’).
last_nameVARCHAR(50)NoneCustomer surname.
signup_dateDATENoneDate the account was created. Used for ORDER BY and date-range filtering.
countryVARCHAR(50)NoneCanada (5), United States (2), United Kingdom (1). Key GROUP BY field for geographic segmentation.
user_typeVARCHAR(50)NoneRetail (5) or Business (3). Used in WHERE filters and GROUP BY summaries.

The transactions table stores financial transaction activity. Each of the eight users has exactly one transaction in the dataset. Transaction 208 (Lucas Taylor, user 8) is a Refund β€” the only non-Purchase transaction β€” making it an important row to isolate with WHERE filters. Amounts range from $29.99 to $149.99, giving a meaningful range for numeric comparisons.

Key Analytical Pattern

Use WHERE amount > 100 to isolate high-value transactions. Use ROUND(amount, 2) in SELECT to display clean decimal output. Use GROUP BY transaction_type with SUM(amount) to compare total revenue by transaction category. Use HAVING SUM(amount) > 500 to show only high-volume categories.

transaction_iduser_idtransaction_dateamounttransaction_type
2011 β€” Ava Brown2024-01-10$49.99Purchase
2022 β€” Liam Wilson2024-01-20$129.98Purchase
2033 β€” Maya Singh2024-02-10$29.99Purchase
2044 β€” Noah Chen2024-02-25$39.99Purchase
2055 β€” Sophia Martin2024-03-12$149.99Purchase
2066 β€” Ethan Davis2024-03-29$79.99Purchase
2077 β€” Isabella Garcia2024-04-09$99.99Purchase
2088 β€” Lucas Taylor2024-04-20$39.99Refund
Column Breakdown
Column NameData TypeConstraintsExplanation
transaction_idINTPRIMARY KEYUnique identifier (201–208).
user_idINTFOREIGN KEY β†’ usersThe customer who generated this transaction. One transaction per user.
transaction_dateDATENoneDate of the transaction. Used in ORDER BY and date-range filtering. Ranges from 2024-01-10 to 2024-04-20.
amountDECIMAL(10,2)NoneTransaction value. Ranges from $29.99 to $149.99. Use ROUND(amount, 2) in SELECT for clean decimal output.
transaction_typeVARCHAR(50)NonePurchase (7) or Refund (1 β€” transaction 208). Used in WHERE and GROUP BY exercises.

The products table stores the product catalogue. Six products span four categories: Software (2), Education (2), Service (1), and Report (1). Unit prices range from $29.99 to $149.99. Products link to order_items via product_id, allowing you to calculate total revenue per product by joining these two tables.

Key Analytical Pattern

Use ORDER BY unit_price ASC with LIMIT to find the cheapest products. Use GROUP BY category with AVG(unit_price) to calculate average price per category. Use HAVING AVG(unit_price) > 50 to identify premium categories.

product_idproduct_namecategoryunit_price
101Analytics Starter KitSoftware$49.99
102Business Dashboard TemplateSoftware$79.99
103Data Cleaning WorkbookEducation$29.99
104SQL Practice PackEducation$39.99
105Premium Support Add-onService$99.99
106Marketing Insights ReportReport$149.99
Column Breakdown
Column NameData TypeConstraintsExplanation
product_idINTPRIMARY KEYUnique identifier (101–106). Referenced by order_items.
product_nameVARCHAR(100)NoneFull product name. Used in SELECT output and LIKE pattern searches.
categoryVARCHAR(50)NoneSoftware (2), Education (2), Service (1), Report (1). Primary GROUP BY field for product analysis.
unit_priceDECIMAL(10,2)NoneList price per unit. Ranges from $29.99 to $149.99. Use ROUND(unit_price, 2) for clean output.

The orders table stores customer order activity. Eight orders cover all eight users β€” one order per user. Six orders are Completed, one is Pending (order 307, Isabella Garcia), and one is Refunded (order 308, Lucas Taylor). The order_status field is the key filtering column for business questions about fulfilment and returns.

Key Analytical Pattern

Use WHERE order_status = β€˜Completed’ to isolate fulfilled orders. Use ORDER BY order_date DESC to see the most recent orders first. Use GROUP BY order_status with COUNT(*) to summarize fulfilment rates. Use HAVING COUNT(*) > 2 to show only statuses with meaningful volume.

order_iduser_idorder_dateorder_status
3011 β€” Ava Brown2024-01-10Completed
3022 β€” Liam Wilson2024-01-20Completed
3033 β€” Maya Singh2024-02-10Completed
3044 β€” Noah Chen2024-02-25Completed
3055 β€” Sophia Martin2024-03-12Completed
3066 β€” Ethan Davis2024-03-29Completed
3077 β€” Isabella Garcia2024-04-09Pending
3088 β€” Lucas Taylor2024-04-20Refunded
Column Breakdown
Column NameData TypeConstraintsExplanation
order_idINTPRIMARY KEYUnique identifier (301–308). Referenced by order_items.
user_idINTFOREIGN KEY β†’ usersThe customer who placed the order. One order per user in this dataset.
order_dateDATENoneDate the order was placed. Ranges from 2024-01-10 to 2024-04-20.
order_statusVARCHAR(50)NoneCompleted (6), Pending (1 β€” order 307), Refunded (1 β€” order 308). Primary WHERE and GROUP BY field.

The order_items table stores the individual products within each order. Nine line items span eight orders β€” order 302 (Liam Wilson) has two line items (products 101 and 102), making it the only multi-product order in the dataset. Each row records the order it belongs to, the product purchased, the quantity, and the pre-calculated line total.

Key Analytical Pattern

Use GROUP BY product_id with SUM(line_total) to calculate total revenue per product. Use HAVING SUM(line_total) > 100 to identify high-revenue products. Use ORDER BY line_total DESC with LIMIT to find the highest-value line items.

order_item_idorder_idproduct_idquantityline_total
401301101 β€” Analytics Starter Kit1$49.99
402302101 β€” Analytics Starter Kit1$49.99
403302102 β€” Business Dashboard Template1$79.99
404303103 β€” Data Cleaning Workbook1$29.99
405304104 β€” SQL Practice Pack1$39.99
406305106 β€” Marketing Insights Report1$149.99
407306102 β€” Business Dashboard Template1$79.99
408307105 β€” Premium Support Add-on1$99.99
409308104 β€” SQL Practice Pack1$39.99
Column Breakdown
Column NameData TypeConstraintsExplanation
order_item_idINTPRIMARY KEYUnique identifier (401–409).
order_idINTFOREIGN KEY β†’ ordersThe parent order. Order 302 has two items (402 and 403); all others have one.
product_idINTFOREIGN KEY β†’ productsThe product purchased. Product 101 appears twice; product 102 appears twice; product 104 appears twice.
quantityINTNoneAll quantities are 1 in this dataset β€” one unit per line item.
line_totalDECIMAL(10,2)NonePre-calculated as unit_price Γ— quantity. The primary aggregation column for product revenue analysis.

The subscriptions table stores recurring customer subscriptions. Eight subscriptions cover all eight users. Six are Active (end_date IS NULL β€” still running), and two are Cancelled (subscriptions 903 and 906, with end_date values). Monthly fees are either $19.99 or $49.99, representing two subscription tiers. The NULL end_dates are central to IS NULL practice exercises.

Key Analytical Pattern

Use WHERE end_date IS NULL to identify active subscriptions. Use WHERE end_date IS NOT NULL to find cancelled ones. Use GROUP BY status with SUM(monthly_fee) to compare revenue by subscription tier. Use HAVING SUM(monthly_fee) > 300 to show only high-value subscription groups.

subscription_iduser_idstart_dateend_datemonthly_feestatus
9011 β€” Ava Brown2024-01-10NULL$19.99Active
9022 β€” Liam Wilson2024-01-20NULL$49.99Active
9033 β€” Maya Singh2024-02-102024-04-10$19.99Cancelled
9044 β€” Noah Chen2024-02-25NULL$19.99Active
9055 β€” Sophia Martin2024-03-12NULL$49.99Active
9066 β€” Ethan Davis2024-03-292024-04-29$19.99Cancelled
9077 β€” Isabella Garcia2024-04-09NULL$49.99Active
9088 β€” Lucas Taylor2024-04-20NULL$19.99Active
Column Breakdown
Column NameData TypeConstraintsExplanation
subscription_idINTPRIMARY KEYUnique identifier (901–908).
user_idINTFOREIGN KEY β†’ usersThe subscribing customer. One subscription per user.
start_dateDATENoneWhen the subscription began. Ranges from 2024-01-10 to 2024-04-20.
end_dateDATENone (NULLable)When the subscription ended. NULL (6) = still active. Date value (2) = cancelled. IS NULL is a key practice operator on this column.
monthly_feeDECIMAL(10,2)None$19.99 (5 users) or $49.99 (3 users). Used in SUM and AVG aggregation exercises.
statusVARCHAR(50)NoneActive (6) or Cancelled (2 β€” subscriptions 903 and 906). Primary GROUP BY field for subscription analysis.

The support_tickets table stores customer support interactions. Eight tickets cover all eight users β€” one ticket per user. Five are Resolved (with a resolved_date), two are Open (resolved_date IS NULL), and one is Pending (resolved_date IS NULL). The NULL resolved_dates represent unresolved cases and are a key field for IS NULL filtering exercises.

Key Analytical Pattern

Use WHERE ticket_status = β€˜Open’ to find unresolved tickets. Use WHERE resolved_date IS NULL to identify all tickets still awaiting resolution. Use GROUP BY ticket_status with COUNT(*) to summarize support workload. Use HAVING COUNT(*) > 1 to show statuses with multiple tickets.

ticket_iduser_idcreated_dateresolved_dateticket_status
8011 β€” Ava Brown2024-01-112024-01-12Resolved
8022 β€” Liam Wilson2024-01-222024-01-25Resolved
8033 β€” Maya Singh2024-02-122024-02-13Resolved
8044 β€” Noah Chen2024-03-01NULLOpen
8055 β€” Sophia Martin2024-03-142024-03-16Resolved
8066 β€” Ethan Davis2024-04-01NULLOpen
8077 β€” Isabella Garcia2024-04-102024-04-12Resolved
8088 β€” Lucas Taylor2024-04-21NULLPending
Column Breakdown
Column NameData TypeConstraintsExplanation
ticket_idINTPRIMARY KEYUnique identifier (801–808).
user_idINTFOREIGN KEY β†’ usersThe customer who raised the ticket. One ticket per user.
created_dateDATENoneDate the ticket was raised. Used in ORDER BY sorting exercises.
resolved_dateDATENone (NULLable)Date resolved. NULL (3 β€” tickets 804, 806, 808) = still open. Use IS NULL to find unresolved tickets.
ticket_statusVARCHAR(50)NoneResolved (5), Open (2 β€” tickets 804, 806), Pending (1 β€” ticket 808). Primary GROUP BY field for support workload analysis.

Quick Reference β€” All 7 Tables

The complete sql_challenges_capstone_course database at a glance.

Users

8 rows β€” Retail/Business, 3 countries. PK: user_id (1–8). Canada has 5 users.

Transactions

8 rows β€” 7 Purchase, 1 Refund. PK: transaction_id (201–208). Amounts $29.99–$149.99.

Products

6 rows β€” 4 categories. PK: product_id (101–106). Prices $29.99–$149.99.

Orders

8 rows β€” 6 Completed, 1 Pending, 1 Refunded. PK: order_id (301–308).

Order Items

9 rows β€” bridge table, qty and line total. PK: order_item_id (401–409). Order 302 = 2 items.

Subscriptions

8 rows β€” 6 Active, 2 Cancelled. PK: subscription_id (901–908). NULL end_date = still active.

Support Tickets

8 rows β€” 5 Resolved, 2 Open, 1 Pending. PK: ticket_id (801–808). NULL resolved_date = unresolved.

SELECT WHERE ORDER BY LIMIT GROUP BY HAVING IS NULL IN BETWEEN LIKE COUNT() SUM() AVG() ROUND() ASC / DESC