平均计算通过消除前10%&使用T-SQL底部10%的值

时间:2017-06-08 22:23:14

标签: sql-server tsql sql-server-2014 percentile

我需要计算一个正在运行的存储过程的平均持续时间。例如,SP的持续时间(以秒为单位)为: 1,30,2,5,2,15,35,7,3,4,2,1,2,40

我必须消除前10%的通话(快速通话)&最低10%的通话(慢速通话)&计算其余的平均值。

是否有更好的方法可以最大限度地降低性能,因为必须定期对庞大的数据集进行操作?

我所知道的方法是:

使用以下查询消除前10%的记录,这会产生两个值(1,1)

SELECT TOP 10 PERCENT WITH TIES value FROM #t order by value asc

底部10%给出(35,40),

SELECT TOP 10 PERCENT WITH TIES value FROM #t order by value desc

消除这些值(1,1,35和40)后,平均值将为7。

3 个答案:

答案 0 :(得分:0)

在我的测试中表现相对较好的一个选项(300,000行不到1秒; 1000万行最多12秒):

declare @tot int = 
(select count(*)
from #MyData)

; with cte as (select Data, ROW_NUMBER() over (order by data) RN from #MyData)

select avg(Data)
from cte
where rn between @tot/10 and 9*@tot/10

答案 1 :(得分:0)

  

编辑以确保均匀“理发”

Declare @YourTable table (Seconds int)
Insert Into @YourTable values
(1),(30),(2),(5),(2),(15),(35),(7),(3),(4),(2),(1),(2),(40)

Select AvgSeconds = avg(Seconds)
 From (
        Select *
              ,Dec1 = NTile(10) over (Order By Seconds)
              ,Dec2 = NTile(10) over (Order By Seconds Desc)
          From  @YourTable
      ) A
 Where Dec1 between 2 and 9
   and Dec2 between 2 and 9

返回

AvgSeconds
7

答案 2 :(得分:0)

略有不同的方法,但如果目标是切断异常值,这应该可行。这理论上应该比使用 NTILE 或 ROW_NUMBER 的其他方法执行得更快,因为它们必须扫描整个结果集然后过滤。这只会扫描它需要的东西,并且应该在正确的索引下表现良好

DROP TABLE IF EXISTS #tbl_test

CREATE TABLE #tbl_test (val INT)
INSERT INTO #tbl_test 
VALUES (1),(30),(2),(5),(2),(15),(35),(7),(3),(4),(2),(1),(2),(40)

Declare @RowCount INT = (SELECT COUNT(*) FROM #tbl_test)
Declare @TenthOfTableRowCount INT = (Select CEILING(@RowCount/10.0))

;WITH cte_Middle80Percent AS (
    SELECT *
    FROM #tbl_test
    ORDER BY val
    OFFSET (@TenthOfTableRowCount) ROWS 
    FETCH NEXT (@RowCount - @TenthOfTableRowCount*2) ROWS ONLY
)

SELECT AVG(val) AS AvgVal
FROM cte_Middle80Percent