ON THIS PAGE
- Understanding the e-commerce data model
- Working with the e-commerce dataset
- Sample analytics on the e-commerce dataset
- Customer lifetime value (LTV)
- Funnel analysis for conversion optimization
- Product recommendations and cross-selling
- Seasonal sales trends and insights
- Customer segmentation for targeted marketing
- Cart abandonment rate
- User purchase frequency distribution
- Optimizing performance
- Appendix: querying the data lake with external tables
This primer introduces data engineers to sample use cases for data-driven decision-making in e-commerce. It walks through ingesting data and exploring performance optimizations using the Firebolt Cloud Data Warehouse, with data from the Open Customer Data Platform (CDP) Project.
## Understanding the e-commerce data model
A well-thought-out schema is critical for efficiently managing the diverse data in an e-commerce warehouse — user interactions, product details, and transaction records. This dataset uses a single-table design:
| Property | Data Type | Description |
|---|---|---|
event_time | TIMESTAMPTZ | Time in UTC |
event_type | TEXT | Customer event (view / cart / purchase) |
product_id | BIGINT | ID of a product |
category_id | TEXT | Product's category ID |
category_code | TEXT | Product's category code |
brand | TEXT | Product brand |
price | NUMERIC(38, 9) | Price of a product |
user_id | TEXT | Permanent user ID |
user_session | TEXT | Temporary user session ID |
The schema supports user identification, event tracking, product trends, and session details for personalization and segmentation.
## Working with the e-commerce dataset
The data comes from a Kaggle dataset loaded into a public Amazon S3 bucket
(firebolt-sample-datasets-public-us-east-1). It spans seven months of activity (October 2019 –
April 2020), roughly 32GB uncompressed as CSV, converted to Parquet for ingestion. Once ingested it
is approximately 412 million records — 52GB uncompressed, 21GB compressed.
Start by creating a database and engine:
CREATE DATABASE ecommercedb WITH DESCRIPTION = 'ECommerce Analytics Primer';CREATE ENGINE ecommerceEngine;START ENGINE ecommerceEngine;USE ENGINE ecommerceEngine;USE ecommercedb;Create the fact table:
CREATE FACT TABLE IF NOT EXISTS "ecommerce" ( "event_time" TIMESTAMPTZ NOT NULL, "event_type" TEXT NOT NULL, "product_id" BIGINT NOT NULL, "category_id" TEXT NULL, "category_code" TEXT NULL, "brand" TEXT NULL, "price" NUMERIC(38, 9) NULL, "user_id" TEXT NULL, "user_session" TEXT NULL);Ingest the data:
COPY INTO ecommerce FROM 's3://firebolt-sample-datasets-public-us-east-1/ecommerce_primer/parquet/'WITH PATTERN='*.gz.parquet' TYPE = PARQUET;SHOW TABLES;## Sample analytics on the e-commerce dataset
### Customer lifetime value (LTV)
Assess the total revenue generated by customers over their engagement with your brand.
SELECT user_id, SUM(price) AS total_revenue, COUNT(DISTINCT user_session) AS total_sessions, (SUM(price) / COUNT(DISTINCT user_session)) AS average_revenue_per_sessionFROM ecommerceWHERE event_type = 'purchase'AND user_session IS NOT NULLGROUP BY user_idORDER BY total_revenue DESC;### Funnel analysis for conversion optimization
Track the customer journey from views to purchases and identify drop-off points.
SELECT event_type, COUNT(DISTINCT user_id) AS unique_usersFROM ecommerceWHERE event_type IN ('view', 'cart', 'purchase')GROUP BY event_typeORDER BY 2 DESC;### Product recommendations and cross-selling
Analyze co-purchase data to reveal products frequently bought together.
WITH CoPurchaseCounts AS ( SELECT a.product_id AS product_A, b.product_id AS product_B, COUNT(*) AS purchase_count FROM ecommerce a JOIN ecommerce b ON a.user_session = b.user_session AND a.product_id < b.product_id WHERE a.event_type = 'purchase' AND b.event_type = 'purchase' GROUP BY a.product_id, b.product_id)SELECT *FROM CoPurchaseCounts cpWHERE purchase_count > 2ORDER BY purchase_count DESCLIMIT 10;### Seasonal sales trends and insights
Analyze sales by month to understand seasonal variation.
SELECT EXTRACT(MONTH FROM event_time) AS sales_month, SUM(price) AS total_revenueFROM ecommerceWHERE event_type = 'purchase'GROUP BY sales_monthORDER BY sales_month;### Customer segmentation for targeted marketing
Segment customers by activity level and average revenue.
WITH CustomerSegments AS ( SELECT user_id, COUNT(DISTINCT user_session) AS session_count, SUM(price) AS total_revenue FROM ecommerce WHERE event_type = 'purchase' GROUP BY user_id)SELECT CASE WHEN session_count <= 5 THEN 'Low Activity' WHEN session_count <= 20 THEN 'Medium Activity' ELSE 'High Activity' END AS segment, COUNT(user_id) AS user_count, AVG(total_revenue) AS avg_revenueFROM CustomerSegmentsGROUP BY segment;### Cart abandonment rate
Identify where potential customers drop off in the purchase process.
WITH CartAbandonment AS ( SELECT event_time::DATE as event_date, user_id, COUNT(CASE WHEN event_type = 'cart' THEN 1 ELSE NULL END) AS cart_count, COUNT(CASE WHEN event_type = 'purchase' THEN 1 ELSE NULL END) AS purchase_count FROM ecommerce WHERE event_type IN ('cart', 'purchase') GROUP BY event_date, user_id)SELECT event_date, COUNT(*) AS total_users, SUM(CASE WHEN cart_count > 0 AND purchase_count = 0 THEN 1 ELSE 0 END) AS abandoned_carts, (SUM(CASE WHEN cart_count > 0 AND purchase_count = 0 THEN 1 ELSE 0 END) * 100.0 / COUNT(*)) AS abandonment_rateFROM CartAbandonmentGROUP BY event_dateORDER BY event_date;### User purchase frequency distribution
Analyze the distribution of user purchase frequencies for marketing planning.
WITH UserPurchaseFrequency AS ( SELECT user_id, COUNT(DISTINCT event_time::DATE) AS purchase_frequency FROM ecommerce WHERE event_type = 'purchase' GROUP BY user_id)SELECT purchase_frequency, COUNT(user_id) AS user_countFROM UserPurchaseFrequencyGROUP BY purchase_frequencyORDER BY purchase_frequency;## Optimizing performance
Use the recommend_ddl command to find an optimal primary index for the workload:
CALL recommend_ddl ( ecommerce, ( SELECT query_text FROM information_schema.engine_query_history where query_text ilike 'select%' and end_time > NOW() - INTERVAL '30 minutes' ));For this workload, Firebolt recommends a primary index on event_type and user_session, which
achieves roughly 94% average data pruning. Recreate the table with that index and reload:
CREATE FACT TABLE IF NOT EXISTS "ecommerce_pi" ( "event_time" TIMESTAMPTZ NOT NULL, "event_type" TEXT NOT NULL, "product_id" BIGINT NOT NULL, "category_id" TEXT NULL, "category_code" TEXT NULL, "brand" TEXT NULL, "price" double precision NULL, "user_id" TEXT NULL, "user_session" TEXT NULL) PRIMARY INDEX event_type, user_session;INSERT INTO ecommerce_pi SELECT * FROM ecommerce;Data analytics is a critical part of e-commerce operations today, and performance and efficiency are essential in cloud-based analytics to avoid slower performance and cost overruns.
## Appendix: querying the data lake with external tables
You can query data directly from S3 without loading it into the warehouse — useful for ad-hoc analysis.
CREATE EXTERNAL TABLE IF NOT EXISTS ex_ecommerce ( event_time TIMESTAMPTZ NOT NULL, event_type TEXT NOT NULL, product_id BIGINT NOT NULL, category_id TEXT NULL, category_code TEXT NULL, brand TEXT NOT NULL, price NUMERIC(38, 9) NULL, user_id TEXT NULL, user_session TEXT NULL) URL = 's3://firebolt-sample-datasets-public-us-east-1/ecommerce_primer/parquet/' OBJECT_PATTERN = '*.gz.parquet' TYPE= (PARQUET);SELECT event_type, count(*)FROM ex_ecommerceGROUP BY ALL;