Я хочу обнаружить выбросы (более чем 20-кратное отклонение от стандартного значения), но я не хочу, чтобы более чем 3-кратные выбросы влияли на среднее значение.Я придумал это:
SELECT d.* FROM
(
SELECT
d.*,
(amount - avg(amount_excl_3z) OVER(PARTITION BY productid)) / NULLIF(STDEV(amount_excl_3z) OVER(PARTITION BY productid), 0) AS zscore_ex
FROM
(
SELECT
d.*,
--when the amount zscore is 3x, null the amount else provide
CASE WHEN ABS(amount - avg(amount) OVER(PARTITION BY productid)) / NULLIF(STDEV(amount) OVER(PARTITION BY productid), 0) > 3
THEN NULL ELSE amount END AS amount_excl_3z
FROM sales d
WHERE --the past year's sales of product 1, but one day I will consider all prods hence why i left the partitions in
timestamp > GETUTCDATE()-365.0 AND
productid = 1
) d
) d
WHERE e.zscore_ex > 20
ORDER BY amount desc
Проблема с данными состоит в том, что, если произойдет слишком много выбросов, они резко повлияют на среднее значение - может быть 1000 случаев продукта с количеством 1, а затем5 вхождений продукта с количеством 20000. Я не хочу, чтобы 20 000 влияли на среднее значение .. Я не хочу, чтобы 50 вхождений из 20 000 влияли на среднее значение .. 500 случаев, хотя это было бы нормально / представляло быновая норма ..
Таким образом, я рассматриваю возможность сделать это, чтобы исключить малые количества массивных выбросов.Если они начинают происходить достаточно часто, чтобы они влияли на среднее значение, достаточное для того, чтобы войти в диапазон, тогда я начну включать их ..
Приведенный выше запрос - мой лучший ответ на "обнаружение выброса, которое пытается исключить небольшое числодикие выбросы от слишком большого влияния »- есть ли какая-либо другая возможность в SQL-сервере, которую я мог бы использовать более эффективно для этого алгоритма?Возможно, какой-то аналитический запрос, который может указать, где на кривой распределения лежит точка?Я посмотрел на PERCENT_RANK, CUME_DIST, PERCENTILE_CONT / DISC, NTILE, но они казались более линейными в распределении выходных данных, чем zscore ..