Kai*_*shu 5 sql-server aggregate sql-server-2012
我计算中位数为:
DECLARE @TEMP TABLE
(
ID INT
)
Select
(
(
Select Top 1 ID
From
(
Select Top 50 Percent ID
From @Temp
Where ID Is NOT NULL
Order By ID
) As A
Order By ID DESC
) +
(
Select Top 1 ID
From
(
Select Top 50 Percent ID
From @Temp
Where ID Is NOT NULL
Order By ID DESC
) As A
Order By ID Asc
)
) / 2
Run Code Online (Sandbox Code Playgroud)
以上查询我想使用。但是,就我而言,columns我想计算的对象太多了MEDIAN。但我认为为每个column. 所以,我试图定义一个单独的函数来接受column值、处理和返回中位数。我应该为此定义table-value-funtion还是有另一种optimized方法?
这个问题与以下问题有关:
Pau*_*ite 11
与您的问题中显示的方法相比,计算简单或分组中位数的方法要有效得多:
2012 年的总冠军是 Peter Larsson 的一种方法。图案是:
SELECT
Median = AVG(1.0 * SQ.YourColumn)
FROM
(
SELECT NumRows = COUNT_BIG(*)
FROM dbo.YourTable
WHERE ColumnName IS NOT NULL
) AS C
CROSS APPLY
(
SELECT YT.ColumnName
FROM dbo.YourTable AS YT
WHERE YT.ColumnName IS NOT NULL
ORDER BY YT.ColumnName ASC
OFFSET (C.NumRows - 1) / 2 ROWS
FETCH NEXT 1 + (1 - C.NumRows % 2) ROWS ONLY
) AS SQ;
Run Code Online (Sandbox Code Playgroud)
SELECT
SQ2.GroupingColumn,
SQ2.Median
FROM
(
SELECT
GroupingColumn,
NumRows = COUNT_BIG(*)
FROM dbo.YourTable
WHERE ColumnName IS NOT NULL
GROUP BY
GroupingColumn
) AS C
CROSS APPLY
(
SELECT
Median = AVG(1.0 * SQ1.YourColumn)
FROM
(
SELECT YT.ColumnName
FROM dbo.YourTable AS YT
WHERE
YT.GroupingColumn = C.GroupingColumn
AND YT.ColumnName IS NOT NULL
ORDER BY
YT.ColumnName ASC
OFFSET (C.NumRows - 1) / 2 ROWS
FETCH NEXT 1 + (1 - C.NumRows % 2) ROWS ONLY
) AS SQ1
) AS SQ2;
Run Code Online (Sandbox Code Playgroud)
为了最大化上述OFFSET方法的性能,您可能需要添加锁定提示(高级主题)。当然,还需要适当的索引。
这很难用 T-SQL 函数直接实现,因为它们不允许执行动态 SQL(假设您正在考虑传入列名)。
有几种方法可以解决这个问题,包括使用一个函数来生成动态 SQL 文本本身,然后可以由调用者执行。问题中没有足够的细节来说明哪种方法最适合您。
如果您想计算中值,有几种方法可以根据您(或其他人)使用的 SQL Server 版本进行计算。Dwain Camps 为 Simple Talk 写了两篇文章,其中他从不同的人那里收集了几个纯 T-SQL 选项,给出了每个选项的示例并比较了它们的性能:
但是,我不认为您可以将这些方法中的任何一个封装到一个函数中以便于重用。为此,您需要使用 SQLCLR 来创建用户定义的聚合(UDA)。几年前我写了一篇文章,展示了如何创建 UDA,以 Median 为例:-)
充分利用 SQL Server 2005 UDT 和 UDA
关于那篇文章,请记住:
GZipStream的东西,改变MaxByteSize从8000到-1。也可以看看: