如何在SQL Server 2012中创建自定义聚合?我试图得到一个中位数聚合。
类似的东西:
;with cte as
(
select top 50 percent val from tbl order by val desc
)
select top 1 from cte
答案 0 :(得分:2)
您应该使用内置函数percentile_cont()
或percentil_disc()
(请参阅here),具体取决于您为偶数条记录定义中位数的方式。
我认为以下是您想要的:
select percentile_cont(0.5) within group (order by val) as median
from tbl;
这比定义自己的功能容易得多。
答案 1 :(得分:1)
答案 2 :(得分:1)
有一篇有趣的文章探讨了解决此问题的多种方法,并提供了性能分析。它声称percentile_cont()表现最差,而这是最好的:
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;
参考:http://www.sqlperformance.com/2012/08/t-sql-queries/median
答案 3 :(得分:0)
这是将宫本武蔵的答案转化为分组查询的一种方法。我使用了Microsoft的Northwind..Orders表来显示Freight列的中位数计算。
SELECT CustomerID, AVG(1.0 * x.Freight), CASE WHEN COUNT(*)%2=1 THEN COUNT(*) ELSE COUNT(*)/2 END AS Cnt
FROM Orders as O1
CROSS APPLY (
SELECT Freight FROM Orders as O2
WHERE O2.CustomerID = O1.CustomerID
ORDER BY Freight
OFFSET (SELECT COUNT(*)-1 FROM Orders as O2 WHERE O2.CustomerID = O1.CustomerID) / 2 ROWS
FETCH NEXT 1 + (1 - (SELECT COUNT(*) FROM Orders as O2 WHERE O2.CustomerID = O1.CustomerID) % 2) ROWS ONLY
) AS x
GROUP BY CustomerID
您在分组查询中可能需要或可能不需要其他聚合,我已经展示了如何获得COUNT(*)。 CROSS APPLY操作为每个CustomerID生成一行,订单数为奇数,并且每个CustomerID生成两行,订单数为偶数,因此要获得COUNT(*)值,您必须除以COUNT(*)值如果是偶数,则在CROSS应用2后,如果是奇数则保持原样。
不确定这是否会有所帮助,并且需要仔细研究以确保它是正确的,但也许这是一个有用的想法。