Sql 自定义聚合函数

Sql 自定义聚合函数,sql,sql-server,tsql,sql-server-2012,Sql,Sql Server,Tsql,Sql Server 2012,如何在SQL Server 2012中创建自定义聚合?我想得到一个中位数 比如: ;with cte as ( select top 50 percent val from tbl order by val desc ) select top 1 from cte 您可能需要阅读以下文章 您可能需要阅读以下文章 您应该只使用内置函数,percentile_cont()或percentile_disc()(请参阅),具体取决于您如何定义偶数记录的中值 我认为以下内容符合您的要求: sel

如何在SQL Server 2012中创建自定义聚合?我想得到一个中位数

比如:

;with cte as 
(
   select top 50 percent val from tbl order by val desc
)
select top 1 from cte

您可能需要阅读以下文章


您可能需要阅读以下文章


您应该只使用内置函数,
percentile_cont()
percentile_disc()
(请参阅),具体取决于您如何定义偶数记录的中值

我认为以下内容符合您的要求:

select percentile_cont(0.5) within group (order by val) as median
from tbl;

这比定义自己的函数容易得多。

您应该只使用内置函数,
percentile_cont()
percentile_disc()
(请参阅),具体取决于您如何定义偶数记录的中值

我认为以下内容符合您的要求:

select percentile_cont(0.5) within group (order by val) as median
from tbl;

这比定义自己的函数容易得多。

有一篇有趣的文章探讨了解决此问题的许多不同方法,并提供了性能分析。它声称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;

参考资料:

有一篇有趣的文章探讨了解决此问题的许多不同方法,并提供了性能分析。它声称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;

参考资料:

这里有一个艰难的转弯方式宮本 武蔵’将答案转换为分组查询。我使用了微软的Northwind..Orders表来显示运费列的中值计算

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(*)。交叉应用操作为每个CustomerID生成一行订单数为奇数的订单,为每个CustomerID生成两行订单数为偶数的订单,因此要获得COUNT(*)值,必须将交叉应用后的计数(*)除以2(如果是偶数),如果是奇数,则保持不变


不确定这是否有帮助,需要仔细研究以确保它是正确的,但也许这是一个有用的想法。

这里有一个很难扭转的方法宮本 武蔵’将答案转换为分组查询。我使用了微软的Northwind..Orders表来显示运费列的中值计算

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(*)。交叉应用操作为每个CustomerID生成一行订单数为奇数的订单,为每个CustomerID生成两行订单数为偶数的订单,因此要获得COUNT(*)值,必须将交叉应用后的计数(*)除以2(如果是偶数),如果是奇数,则保持不变


不确定这是否有帮助,需要仔细研究以确保其正确性,但可能这是一个有用的想法。

我想要一个聚合的原因是,我可以在group by中的group上使用它。我想要聚合的原因是,我可以在group by中的group上使用它。