私は中央値を次のように計算しています:
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
上記のクエリを使用します。しかし、私の場合、columns
を計算したい人にはMEDIAN
がたくさんあります。しかし、column
ごとに上記のコードブロックを繰り返すのは良くないと思います。したがって、column
値を受け入れ、処理して中央値を返す個別の関数を定義しようとしています。そのためにtable-value-funtion
を定義する必要がありますか、それとも別のoptimized
方法がありますか?
この質問は、次の質問に関連しています。
単純な中央値またはグループ化された中央値を計算するには、質問で示した方法よりもはるかに効率的な方法があります。
中央値を計算する最も速い方法は何ですか?
グループ化された中央値に対する最善のアプローチ
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;
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;
上記のOFFSET
メソッドのパフォーマンスを最大化するには、 ロックのヒントを追加する (高度なトピック)が必要になる場合があります。もちろん、適切な索引付けも必要です。
これは動的SQLの実行を許可しないため、T-SQL関数を使用して直接達成することは困難です(列名を渡すことを考えていた場合)。
これを回避する方法はいくつかあります。たとえば、関数を使用して動的SQLテキスト自体を生成し、それを呼び出し元が実行できるようにします。質問には、どのアプローチがあなたに最も適しているかを説明するのに十分な詳細がありません。
中央値を計算する場合、使用しているSQL Serverのバージョン(または他の誰か)によっては、いくつかの方法があります。 Dwain CampsはSimple Talkについて2つの記事を書き、さまざまな人々からいくつかの純粋なT-SQLオプションを収集し、それぞれの例を示し、それらのパフォーマンスを比較しました。
ただし、これらのメソッドを関数にカプセル化して簡単に再利用できるとは思いません。そのためには、SQLCLRを使用して ser-Defined Aggregate (UDA)を作成する必要があります。 Medianを例にしてUDAを作成する方法を示す記事を数年前に書きました:-)
SQL Server 2005 UDTとUDAを最大限に活用する
その記事に関して、覚えておいてください:
GZipStream
を削除してMaxByteSize
を8000
から-1
に変更するのはかなり簡単です。以下も参照してください。