如何在 TSQL 中排除 1800 万条记录的最高和最低 5% 的年薪,然后使用所选数据计算平均值

Posted

技术标签:

【中文标题】如何在 TSQL 中排除 1800 万条记录的最高和最低 5% 的年薪,然后使用所选数据计算平均值【英文标题】:How do I exclude top and bottom 5% of annual salary on 18 million records in TSQL, then use the seleced data to calculate average 【发布时间】:2015-08-24 23:49:14 【问题描述】:

我在一列(收入)中有 1800 万行,我想排除收入的最高和最低 5% 以计算更准确的平均收入。

【问题讨论】:

计算PERCENT_RANK,缩小数据并计算AVG。 【参考方案1】:

您没有提供任何关于结构、分组等的数据。所以这是概念证明。 计算PERCENT_RANK(),缩小数据,计算平均值。

SqlFiddleDemo

/* Preparing data */
CREATE TABLE tab(id INT IDENTITY(1,1), income INT)

;WITH Nums(Number) AS
(SELECT 1 AS Number
  UNION ALL
 SELECT Number+1 FROM Nums where Number<100   /* Warn here recursive CTE */
)
INSERT INTO tab(income)
SELECT Number FROM Nums;


/* Main query */
WITH cte(id, income, [percent]) AS
(
  SELECT 
       id
      ,income
      ,[percent] = PERCENT_RANK() OVER(ORDER BY income)
  FROM tab
)
SELECT [average_income] =  AVG(income)
FROM cte
WHERE 
   [percent] > 0.05 
   AND [percent] < 0.95

【讨论】:

【参考方案2】:
with top5 as 
(select top 5 percent income from tablename)
, bottom5 as
(select top 5 percent income from tablename order by income desc)
select avg(income)
from tablename
where income not in (select income from top5 union all select income from bottom5)

您可以通过计算前 5% 和后 5%,然后使用 not in 从最终计算中排除它们来做到这一点。

【讨论】:

NOT IN 将排除中间 90% 中与其他 10% 没有区别的值,从而更改“平均值”。【参考方案3】:

这有点棘手。 Percentile_rank() 可能是要走的路。但是,以下可能会更快:

select t.*
from table t cross join
     (select max(salary) as maxs
      from (select top 5 percent salary
            from table t
            order by salary
           ) t
     ) m1 cross join
     (select min(salary) as mins
      from (select top 5 percent salary
            from table t
            order by salary desc
           )
    ) m2
where s.salary >= mins and s.salary <= maxs;

这个想法是 min 和 max 的子查询可以有效地使用索引来获取 5% 和 95% 的值。查询的其余部分将只是全表扫描。

【讨论】:

许多收入值可能会落在行中,因此您不能将它们的值用作过滤器。您必须计算出 5% 的行数。 @TomBlodget 。 . .我很困惑。你不是 OP,你怎么知道数据是什么样子的。 这个问题给出了一个普遍的问题。如果此答案针对更具体的答案进行了优化,请直说。

以上是关于如何在 TSQL 中排除 1800 万条记录的最高和最低 5% 的年薪,然后使用所选数据计算平均值的主要内容,如果未能解决你的问题,请参考以下文章

TSQL - 排除与临时表匹配的行

如何使用 TSQL 而不是 linq 获取和跳过记录 [重复]

在 where 子句中使用 DATEADD 的 TSQL 性能问题

在 TSQL 中,如何添加一个计数列来计算查询中的行数?

TSQL - 替换 isnumeric = 0

当有大约 100 万条记录时,如何在 Java 中比较 Hive 和 Cassandra 数据