-- Base aggregation: Daily product performance
CREATE MATERIALIZED VIEW daily_product_metrics AS
SELECT
DATE_TRUNC('day', o.created_at) as day,
p.id as product_id,
p.name as product_name,
p.category,
COUNT(DISTINCT oi.order_id) as order_count,
SUM(oi.quantity) as units_sold,
SUM(oi.quantity * oi.price) as revenue,
AVG(oi.quantity * oi.price) as avg_order_value,
COUNT(DISTINCT o.user_id) as unique_customers
FROM order_items oi
JOIN orders o ON oi.order_id = o.id
JOIN products p ON oi.product_id = p.id
GROUP BY day, p.id, p.name, p.category;
-- Layer 2: Weekly rollups
CREATE MATERIALIZED VIEW weekly_product_metrics AS
SELECT
DATE_TRUNC('week', day) as week,
product_id,
product_name,
category,
SUM(order_count) as weekly_orders,
SUM(units_sold) as weekly_units,
SUM(revenue) as weekly_revenue,
AVG(avg_order_value) as avg_order_value
FROM daily_product_metrics
GROUP BY week, product_id, product_name, category;
-- Layer 3: Category performance
CREATE MATERIALIZED VIEW category_performance AS
SELECT
category,
COUNT(DISTINCT product_id) as product_count,
SUM(weekly_revenue) as total_revenue,
SUM(weekly_units) as total_units,
AVG(weekly_revenue) as avg_product_revenue
FROM weekly_product_metrics
WHERE week >= DATE_TRUNC('week', NOW()) - INTERVAL '12 weeks'
GROUP BY category
HAVING SUM(weekly_revenue) > 10000;
-- Layer 4: Top performers
CREATE MATERIALIZED VIEW top_products_last_30d AS
SELECT DISTINCT ON(category)
category,
product_id,
product_name,
SUM(revenue) as revenue_30d
FROM daily_product_metrics
WHERE day >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY category, product_id, product_name
ORDER BY category, revenue_30d DESC;