Yaa*_*lis 212 sql sql-server aggregate-functions median
根据MSDN,Median不能作为Transact-SQL中的聚合函数使用.但是,我想知道是否可以创建此功能(使用Create Aggregate函数,用户定义函数或其他方法).
这样做的最佳方式(如果可能) - 允许在聚合查询中计算中值(假设数值数据类型)?
Jef*_*ood 194
如果您使用的是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
Run Code Online (Sandbox Code Playgroud)
Jus*_*ant 129
有很多方法可以做到这一点,性能差异很大.这是一个特别优化的解决方案,来自Medians,ROW_NUMBERs和性能.当涉及到执行期间生成的实际I/O时,这是一个特别优化的解决方案 - 它看起来比其他解决方案更昂贵,但它实际上要快得多.
该页面还包含对其他解决方案和性能测试详细信息的讨论.请注意,如果有多个行具有相同的中间列值,则使用唯一列作为消歧器.
与所有数据库性能方案一样,始终尝试使用真实硬件上的实际数据测试解决方案 - 您永远不知道对SQL Server优化程序的更改或环境中的特性何时会使正常快速的解决方案变慢.
DECLARE @c BIGINT = (SELECT COUNT(*) FROM dbo.EvenRows);
SELECT AVG(1.0 * val)
FROM (
SELECT val FROM dbo.EvenRows
ORDER BY val
OFFSET (@c - 1) / 2 ROWS
FETCH NEXT 1 + (1 - @c % 2) ROWS ONLY
) AS x;
Run Code Online (Sandbox Code Playgroud)
Sim*_*ver 78
在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
Run Code Online (Sandbox Code Playgroud)
另见:http://blog.sqlauthority.com/2011/11/20/sql-server-introduction-to-percentile_cont-analytic-functions-introduced-in-sql-server-2012/
Sir*_*bin 21
我原来的快速回答是:
select max(my_column) as [my_column], quartile
from (select my_column, ntile(4) over (order by my_column) as [quartile]
from my_table) i
--where quartile = 2
group by quartile
Run Code Online (Sandbox Code Playgroud)
这将一举为您提供中位数和四分位数范围.如果你真的只想要一行是中位数,那么取消注释where子句.
当你坚持使用解释计划时,60%的工作是对数据进行排序,这在计算像这样的位置相关统计数据时是不可避免的.
我修改了答案,遵循RobertŠevčík-Robajz在以下评论中提出的出色建议:
;with PartitionedData as
(select my_column, ntile(10) over (order by my_column) as [percentile]
from my_table),
MinimaAndMaxima as
(select min(my_column) as [low], max(my_column) as [high], percentile
from PartitionedData
group by percentile)
select
case
when b.percentile = 10 then cast(b.high as decimal(18,2))
else cast((a.low + b.high) as decimal(18,2)) / 2
end as [value], --b.high, a.low,
b.percentile
from MinimaAndMaxima a
join MinimaAndMaxima b on (a.percentile -1 = b.percentile) or (a.percentile = 10 and b.percentile = 10)
--where b.percentile = 5
Run Code Online (Sandbox Code Playgroud)
当您拥有偶数个数据项时,这应该计算正确的中位数和百分位数值.如果您只想要中位数而不是整个百分位数分布,请再次取消注释最终的where子句.
l--*_*''' 18
更好的是:
SELECT @Median = AVG(1.0 * val)
FROM
(
SELECT o.val, rn = ROW_NUMBER() OVER (ORDER BY o.val), c.c
FROM dbo.EvenRows AS o
CROSS JOIN (SELECT c = COUNT(*) FROM dbo.EvenRows) AS c
) AS x
WHERE rn IN ((c + 1)/2, (c + 2)/2);
Run Code Online (Sandbox Code Playgroud)
来自大师自己,Itzik Ben-Gan!
MS SQL Server 2012(及更高版本)具有PERCENTILE_DISC函数,该函数计算排序值的特定百分位数.PERCENTILE_DISC(0.5)将计算中位数 - https://msdn.microsoft.com/en-us/library/hh231327.aspx
| 归档时间: |
|
| 查看次数: |
401200 次 |
| 最近记录: |