Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 使用T-SQL消除前10%和后10%值的平均计算_Sql Server_Tsql_Sql Server 2014_Percentile - Fatal编程技术网

Sql server 使用T-SQL消除前10%和后10%值的平均计算

Sql server 使用T-SQL消除前10%和后10%值的平均计算,sql-server,tsql,sql-server-2014,percentile,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

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

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

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
编辑以确保发型均匀

返回

AvgSeconds
7

方法稍有不同,但若目标是切断异常值,那个么这应该是可行的。从理论上讲,这应该比使用NTILE或ROW_编号的其他方法执行得更快,因为这些方法必须扫描整个结果集,然后进行过滤。这将只扫描它需要的内容,并且在使用正确的索引时应该表现良好

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

根据您的样本数据,预期结果是什么?前10%是指按计数消除10%的结果,而不是那些属于前10%最快性能的结果,对吗?所以,如果你有10个结果,你会消除顶部的一个,底部的一个,即使顶部或底部有重复的值,你只会扔掉一个,然后平均剩下的,对吗?我只是想澄清一下。是的,我在我的问题中添加了更多的细节。你知道的方法有什么问题吗?例如,从t中选择AVGvalue*1.0,其中值不在从t ORDER BY value中选择带有TIES值的前10%中,值不在从t ORDER BY value DESC中选择带有TIES值的前10%。@sqlcheckpoint下面的答案是否解决了您的问题?尽管这似乎是NTILE实际有用的少数情况之一,NTILE的问题是,如果本例中的整数10不能均匀地除以总计数,那么本例中的整数14就不能均匀地除以。在本例中,结果是不均匀的,从底部算起2个,从顶部算起1个。@ZLK True,但我倾向于使用较大的样本,因此任何差异都会消失在尘埃中。不过,我确实做了一次编辑,以确保发型均匀。谢谢你的留言。
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