函数来计算SQL Server中的中位数

根据MSDN,Median在Transact-SQL中不可用作聚合函数。 但是,我想知道是否可以创建此功能(使用创建聚合函数,用户定义函数或其他方法)。

什么是最好的方式(如果可能的话) - 允许计算聚合查询中的中值(假设为数值数据类型)?


有很多方法可以做到这一点,并且性能大幅变化。 以下是Medians,ROW_NUMBER和性能特别优化的解决方案。 当涉及到执行期间生成的实际I / O时,这是一个特别优化的解决方案 - 它看起来比其他解决方案成本更高,但实际上它要快得多。

该页面还包含对其他解决方案和性能测试细节的讨论。 请注意,如果有多个行的中值列的值相同,则使用唯一列作为消除歧义。

与所有数据库性能场景一样,总是尝试使用真实硬件上的实际数据来测试解决方案 - 您永远不知道何时对SQL Server优化器的更改或环境中的特性会使正常速度的解决方案变慢。

SELECT
   CustomerId,
   AVG(TotalDue)
FROM
(
   SELECT
      CustomerId,
      TotalDue,
      -- SalesOrderId in the ORDER BY is a disambiguator to break ties
      ROW_NUMBER() OVER (
         PARTITION BY CustomerId
         ORDER BY TotalDue ASC, SalesOrderId ASC) AS RowAsc,
      ROW_NUMBER() OVER (
         PARTITION BY CustomerId
         ORDER BY TotalDue DESC, SalesOrderId DESC) AS RowDesc
   FROM Sales.SalesOrderHeader SOH
) x
WHERE
   RowAsc IN (RowDesc, RowDesc - 1, RowDesc + 1)
GROUP BY CustomerId
ORDER BY CustomerId;

如果您使用的是SQL 2005或更高版本,则对于表中的单个列来说,这是一个很好的简单中值计算:

SELECT
(
 (SELECT MAX(Score) FROM
   (SELECT TOP 50 PERCENT Score FROM Posts ORDER BY Score) AS BottomHalf)
 +
 (SELECT MIN(Score) FROM
   (SELECT TOP 50 PERCENT Score FROM Posts ORDER BY Score DESC) AS TopHalf)
) / 2 AS Median

在SQL Server 2012中,您应该使用PERCENTILE_CONT:

SELECT SalesOrderID, OrderQty,
    PERCENTILE_CONT(0.5) 
        WITHIN GROUP (ORDER BY OrderQty)
        OVER (PARTITION BY SalesOrderID) AS MedianCont
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN (43670, 43669, 43667, 43663)
ORDER BY SalesOrderID DESC

另见:http://blog.sqlauthority.com/2011/11/20/sql-server-introduction-to-percentile_cont-analytic-functions-introduced-in-sql-server-2012/

链接地址: http://www.djcxy.com/p/83821.html

上一篇: Function to Calculate Median in SQL Server

下一篇: Simple way to calculate median with MySQL