2010-03-05 51 views
2

我有以下SQL表 -SQL:顯示平均和最大/最小標準差範圍內

Date  StoreNo  Sales 
23/4   34  4323.00 
23/4   23  564.00 
24/4   34  2345.00 
etc 

我正在返回平均銷售額,最大的銷售及分銷售一段時間的查詢 -

select avg(Sales), max(sales), min(sales) 
from tbl_sales 
where date between etc 

但是在最小值和最大值中都會出現一些非常極端的值 - 可能是因爲數據輸入不好,可能是因爲當天發生了一些異常現象並且存儲。

我想要的是一個返回平均值,最大值和最小值的查詢,但不知何故排除了極值。我對此如何開放,但也許它會以某種方式使用標準偏差(例如,僅在真正的平均值的x標準開發中使用數據)。

非常感謝

回答

3

爲了計算標準差,則需要通過所有元素的迭代,所以這將是不可能做到這一點的一個查詢。偷懶的方法是隻做兩遍:

DECLARE 
    @Avg int, 
    @StDev int 

SELECT @Avg = AVG(Sales), @StDev = STDEV(Sales) 
FROM tbl_sales 
WHERE ... 

SELECT AVG(Sales) AS AvgSales, MAX(Sales) AS MaxSales, MIN(Sales) AS MinSales 
FROM tbl_sales 
WHERE ... 
AND Sales >= @Avg - @StDev * 3 
AND Sales <= @Avg + @StDev * 3 

另一個簡單的選項,威力工作(在科學數據的分析很常見)將只下降最小和最大X值,如果你有很多數據需要處理的話,這種方法很有效。您可以使用ROW_NUMBER爲此在一個聲明:

WITH OrderedValues AS 
(
    SELECT 
     Sales, 
     ROW_NUMBER() OVER (ORDER BY Sales) AS RowNumAsc, 
     ROW_NUMBER() OVER (ORDER BY Sales DESC) AS RowNumDesc 
) 
SELECT ... 
FROM tbl_sales 
WHERE ... 
AND Sales > 
(
    SELECT MAX(Sales) 
    FROM OrderedValues 
    WHERE RowNumAsc <= @ElementsToDiscard 
) 
AND Sales < 
(
    SELECT MIN(Sales) 
    FROM OrderedValues 
    WHERE RowNumDesc <= @ElementsToDiscard 
) 

更換ROW_NUMBERRANKDENSE_RANK,如果您想放棄一定數量的獨特值。

除了這些簡單的技巧,你開始進入一些相當重的統計。我必須處理類似的驗證,並且對於SO帖子而言,它的材料太多了。有一百種不同的算法,你可以用十幾種不同的方法調整。如果可能,我會盡量保持簡單!

1

也許你在找什麼是percentiles

標準偏差往往對異常值敏感,因爲它是使用值和平均值之差的平方來計算的。

也許一個更強大,更不敏感的測量,如價值和平均值之間的差異的絕對值將更適合您的情況。

2

擴展在DuffyMo的帖子,你可以做類似

With SalesStats As 
    (
    Select Sales, NTILE(100) OVER (Order By Sales) As NtileNum 
    From tbl_Sales 
    ) 
Select Avg(Sales), Max(Sales), Min(Sales) 
From SalesStats 
Where NtileNum Between 5 And 95 

這將排除的最低5%和最高的95%。如果您的數字變化很大,您可能會發現平均值不是質量彙總統計量,應該考慮使用中值。你可以這樣做:

With SalesStats As 
    (
    Select NTILE(100) OVER (Order By Sales) As NtileNum 
     , ROW_NUMBER() OVER (Order By Id) As RowNum 
    From tbl_Sales 
    ) 
    , TotalSalesRows 
     (
     Select COUNT(*) As Total 
     From tbl_Sales 
     ) 
    , Median As 
     (
     Select Sales 
     From SalesStats 
      Cross Join TotalSalesRows 
     Where RowNum In ((TotalRows.Total + 1)/2, (TotalRows.Total + 2)/2) 
     ) 
Select Avg(Sales), Max(Sales), Min(Sales), Median.Sales 
From SalesStats 
    Cross Join Median 
Where NtileNum Between 5 And 95 
+0

正確使用中間值與平均值的差異數據;請注意,可以通過在同一個CTE中放置COUNT(*)和ROW_NUMBER來完成中間查詢,並且應該選擇AVG(銷售),除非當計數爲真時需要兩個彙總行甚至。 – Aaronaught

+0

對於第一個代碼塊,以下行必須包含Sales以獲得AVG(銷售):選擇Sales,NTILE(100)OVER(Order By Sales)作爲NtileNum – KAE

+0

@KE - 我的監督。已更正。謝謝。 – Thomas

相關問題