我需要计算一个正在运行的存储过程的平均持续时间。例如,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。
答案 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