我有一个简单的MEDIAN计算功能:
IF OBJECT_ID(N'COMPUTEMEDIAN', N'FN') IS NOT NULL
DROP FUNCTION dbo.COMPUTEMEDIAN;
GO
CREATE FUNCTION dbo.COMPUTEMEDIAN(@VALUES NVARCHAR(MAX))
RETURNS DECIMAL
WITH EXECUTE AS CALLER
AS
BEGIN
DECLARE @SQL NVARCHAR(MAX)
DECLARE @MEDIAN DECIMAL
SET @MEDIAN = 0.0;
DECLARE @MEDIAN_TEMP TABLE (RawValue DECIMAL);
-- This is the Killer!
INSERT INTO @MEDIAN_TEMP
SELECT s FROM master.dbo.Split(',', @VALUES) OPTION(MAXRECURSION 0)
SELECT @MEDIAN =
(
(SELECT MAX(RawValue) FROM
(SELECT TOP 50 PERCENT RawValue FROM @MEDIAN_TEMP ORDER BY RawValue) AS BottomHalf)
+
(SELECT MIN(RawValue) FROM
(SELECT TOP 50 PERCENT RawValue FROM @MEDIAN_TEMP ORDER BY RawValue DESC) AS TopHalf)
) / 2
--PRINT @SQL
RETURN @MEDIAN;
END;
GO
但是,我的表格如下:
CREATE TABLE #TEMP (GroupName VARCHAR(MAX), Value DECIMAL)
INSERT INTO #TEMP VALUES ('A', 1.0)
INSERT INTO #TEMP VALUES ('A', 2.0)
INSERT INTO #TEMP VALUES ('A', 3.0)
INSERT INTO #TEMP VALUES ('A', 4.0)
INSERT INTO #TEMP VALUES ('B', 10.0)
INSERT INTO #TEMP VALUES ('B', 11.0)
INSERT INTO #TEMP VALUES ('B', 12.0)
SELECT * FROM #TEMP
DROP TABLE #TEMP
使用MEDIAN
列上的GROUP BY
调用此表中的id
函数的最佳方法是什么?所以,我正在寻找这样的事情:
SELECT id, COMPUTEMEDIAN(Values)
FROM #TEMP
GROUP BY id
我当前的方法是使用XMLPATH
将GROUP BY
操作产生的所有值组合成一个大字符串,然后将其传递给函数,但这涉及String拆分操作,对于大字符串,这只是放慢一切。有什么建议吗?
答案 0 :(得分:1)
由于您使用的是SQL Server 2008,我建议将聚合函数编写为CLR函数。
http://msdn.microsoft.com/en-us/library/91e6taax(v=vs.80).aspx
此外,人们之前已经问过这个问题。也许他们的答案会有所帮助
答案 1 :(得分:1)
编辑:我可以确认这在大型数据库上非常有效(30,000个值)
嗯...刚刚遇到this所以以下工作完全正常,但我不确定它会变得多么昂贵:
SELECT
GroupName,
AVG(Value)
FROM
(
SELECT
GroupName,
cast(Value as decimal(5,2)) Value,
ROW_NUMBER() OVER (
PARTITION BY GroupName
ORDER BY Value ASC) AS RowAsc,
ROW_NUMBER() OVER (
PARTITION BY GroupName
ORDER BY Value DESC) AS RowDesc
FROM #TEMP SOH
) x
WHERE
RowAsc IN (RowDesc, RowDesc - 1, RowDesc + 1)
GROUP BY GroupName
ORDER BY GroupName;
答案 2 :(得分:1)
无需使用用户定义的功能!我就是这样做的:
CREATE TABLE #TEMP (id VARCHAR(MAX), Value DECIMAL)
INSERT INTO #TEMP VALUES('A', 1.0)
INSERT INTO #TEMP VALUES('A', 2.0)
INSERT INTO #TEMP VALUES('A', 3.0)
INSERT INTO #TEMP VALUES('A', 4.0)
INSERT INTO #TEMP VALUES('B', 10.0)
INSERT INTO #TEMP VALUES('B', 11.0)
INSERT INTO #TEMP VALUES('B', 12.0)
SELECT
(SELECT TOP 1 Value
FROM (SELECT TOP(calcs.medianIndex) Value
FROM #temp
WHERE #temp.ID = calcs.ID ORDER BY Value ASC) AS subSet
ORDER BY subSet.Value DESC), ID
FROM
(SELECT
CASE WHEN count(*) % 2 = 1 THEN count(*)/2 + 1
ELSE count(*)/2
END AS medianIndex,
ID
FROM #TEMP
GROUP BY ID) AS calcs
DROP TABLE #TEMP
当有偶数记录时,可能要仔细检查行为。
编辑:在您的Median函数中查看您的工作后,我意识到我的答案基本上只是将您的工作移出函数并进入常规查询。那么......为什么你的中位数计算必须在用户定义的函数内?看起来很多 这样比较困难。