Try to speed up brand calcs

This commit is contained in:
2025-02-10 10:20:32 -05:00
parent d936d50f83
commit 3d2d1b3946

View File

@@ -138,11 +138,11 @@ async function calculateBrandMetrics(startTime, totalProducts, processedCount =
p.brand, p.brand,
COUNT(DISTINCT p.pid) as product_count, COUNT(DISTINCT p.pid) as product_count,
COUNT(DISTINCT CASE WHEN p.visible = true THEN p.pid END) as active_products, COUNT(DISTINCT CASE WHEN p.visible = true THEN p.pid END) as active_products,
SUM(p.stock_quantity) as total_stock_units, COALESCE(SUM(p.stock_quantity), 0) as total_stock_units,
SUM(p.stock_quantity * p.cost_price) as total_stock_cost, COALESCE(SUM(p.stock_quantity * p.cost_price), 0) as total_stock_cost,
SUM(p.stock_quantity * p.price) as total_stock_retail, COALESCE(SUM(p.stock_quantity * p.price), 0) as total_stock_retail,
SUM(pm.total_revenue) as total_revenue, COALESCE(SUM(pm.total_revenue), 0) as total_revenue,
AVG(pm.avg_margin_percent) as avg_margin COALESCE(AVG(NULLIF(pm.avg_margin_percent, 0)), 0) as avg_margin
FROM products p FROM products p
FORCE INDEX (idx_brand) FORCE INDEX (idx_brand)
LEFT JOIN product_metrics pm FORCE INDEX (PRIMARY) ON p.pid = pm.pid LEFT JOIN product_metrics pm FORCE INDEX (PRIMARY) ON p.pid = pm.pid
@@ -158,32 +158,42 @@ async function calculateBrandMetrics(startTime, totalProducts, processedCount =
GROUP BY p.brand GROUP BY p.brand
`, [batch.map(row => row.brand), lastCalculationTime, lastCalculationTime]); `, [batch.map(row => row.brand), lastCalculationTime, lastCalculationTime]);
// Populate sales stats with optimized index usage // Populate sales stats with optimized date handling
await connection.query(` await connection.query(`
INSERT INTO temp_sales_stats INSERT INTO temp_sales_stats
WITH date_ranges AS (
SELECT
DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) as current_start,
CURRENT_DATE as current_end,
DATE_SUB(CURRENT_DATE, INTERVAL 60 DAY) as previous_start,
DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) as previous_end
)
SELECT SELECT
p.brand, p.brand,
SUM(CASE COALESCE(SUM(
WHEN o.date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) CASE WHEN o.date >= dr.current_start
THEN o.quantity * o.price THEN o.quantity * o.price
ELSE 0 ELSE 0
END) as current_period_sales, END
SUM(CASE ), 0) as current_period_sales,
WHEN o.date BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 60 DAY) AND DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) COALESCE(SUM(
CASE WHEN o.date >= dr.previous_start AND o.date < dr.current_start
THEN o.quantity * o.price THEN o.quantity * o.price
ELSE 0 ELSE 0
END) as previous_period_sales END
), 0) as previous_period_sales
FROM products p FROM products p
FORCE INDEX (idx_brand) FORCE INDEX (idx_brand)
INNER JOIN orders o FORCE INDEX (idx_orders_metrics) ON p.pid = o.pid INNER JOIN orders o FORCE INDEX (idx_orders_metrics) ON p.pid = o.pid
AND o.canceled = false CROSS JOIN date_ranges dr
AND o.date >= DATE_SUB(CURRENT_DATE, INTERVAL 60 DAY)
AND o.updated > ?
WHERE p.brand IN (?) WHERE p.brand IN (?)
AND o.canceled = false
AND o.date >= dr.previous_start
AND o.updated > ?
GROUP BY p.brand GROUP BY p.brand
`, [lastCalculationTime, batch.map(row => row.brand)]); `, [batch.map(row => row.brand), lastCalculationTime]);
// Update metrics using temp tables // Update metrics using temp tables with optimized calculations
await connection.query(` await connection.query(`
INSERT INTO brand_metrics ( INSERT INTO brand_metrics (
brand, brand,
@@ -199,19 +209,19 @@ async function calculateBrandMetrics(startTime, totalProducts, processedCount =
) )
SELECT SELECT
ps.brand, ps.brand,
COALESCE(ps.product_count, 0) as product_count, ps.product_count,
COALESCE(ps.active_products, 0) as active_products, ps.active_products,
COALESCE(ps.total_stock_units, 0) as total_stock_units, ps.total_stock_units,
COALESCE(ps.total_stock_cost, 0) as total_stock_cost, ps.total_stock_cost,
COALESCE(ps.total_stock_retail, 0) as total_stock_retail, ps.total_stock_retail,
COALESCE(ps.total_revenue, 0) as total_revenue, ps.total_revenue,
COALESCE(ps.avg_margin, 0) as avg_margin, ps.avg_margin,
CASE CASE
WHEN COALESCE(ss.previous_period_sales, 0) = 0 AND COALESCE(ss.current_period_sales, 0) > 0 THEN 100 WHEN COALESCE(ss.previous_period_sales, 0) = 0 AND COALESCE(ss.current_period_sales, 0) > 0 THEN 100
WHEN COALESCE(ss.previous_period_sales, 0) = 0 THEN 0 WHEN COALESCE(ss.previous_period_sales, 0) = 0 THEN 0
ELSE LEAST(999.99, GREATEST(-100, ELSE ROUND(LEAST(999.99, GREATEST(-100,
((COALESCE(ss.current_period_sales, 0) / ss.previous_period_sales) - 1) * 100 ((ss.current_period_sales / NULLIF(ss.previous_period_sales, 0)) - 1) * 100
)) )), 2)
END as growth_rate, END as growth_rate,
NOW() as last_calculated_at NOW() as last_calculated_at
FROM temp_product_stats ps FROM temp_product_stats ps