34 lines
1.4 KiB
SQL
34 lines
1.4 KiB
SQL
WITH RECURSIVE calendar(day, last_day) AS (
|
|
SELECT MIN(order_date), MAX(order_date) FROM daily_category_revenue
|
|
HAVING COUNT(*) > 0
|
|
UNION ALL
|
|
SELECT date(day, '+1 day'), last_day FROM calendar WHERE day < last_day
|
|
),
|
|
categories AS (
|
|
SELECT DISTINCT category FROM daily_category_revenue
|
|
),
|
|
daily AS (
|
|
SELECT day, c.category, COALESCE(r.revenue_kopecks, 0) AS revenue_kopecks
|
|
FROM calendar CROSS JOIN categories AS c
|
|
LEFT JOIN daily_category_revenue AS r ON r.order_date = day AND r.category = c.category
|
|
),
|
|
-- Вычитаем общий для категории минимум в целых копейках до перехода AVG к REAL.
|
|
-- Такой сдвиг сохраняет отклонения и различия в копейку при большом базовом уровне.
|
|
shifted AS (
|
|
SELECT *, revenue_kopecks - MIN(revenue_kopecks) OVER (PARTITION BY category) AS amount
|
|
FROM daily
|
|
),
|
|
deviations AS (
|
|
SELECT *, amount - AVG(amount) OVER (PARTITION BY category) AS deviation
|
|
FROM shifted
|
|
),
|
|
stats AS (
|
|
SELECT *, COUNT(*) OVER (PARTITION BY category) AS days,
|
|
AVG(deviation * deviation) OVER (PARTITION BY category) AS variance
|
|
FROM deviations
|
|
)
|
|
SELECT day AS order_date, category, revenue_kopecks
|
|
FROM stats
|
|
WHERE days >= 7 AND variance > 0 AND deviation * deviation > 4 * variance
|
|
ORDER BY day, category;
|