クエリをOracleからSQL Server 2014に移行しようとしています。
これがOracleでうまく機能する私のクエリです:
select
count(distinct A) over (partition by B) / count(*) over() as A_B
from MyTable
SQL Server 2014でこのクエリを実行しようとした後のエラーは次のとおりです。
Use of DISTINCT is not allowed with the OVER clause
誰が問題なのか知っていますか? SQL Serverでこのようなクエリは可能ですか?お知らせ下さい。
誰が問題なのか知っていますか? SQL Serverでこのようなクエリは可能ですか?
いいえ、現在実装されていません。次の接続アイテムのリクエストを参照してください。
別の可能なバリアントは
_SELECT M.A,
M.B,
T.A_B
FROM MyTable M
JOIN (SELECT CAST(COUNT(DISTINCT A) AS NUMERIC(18,8)) / SUM(COUNT(*)) OVER() AS A_B,
B
FROM MyTable
GROUP BY B) T
ON EXISTS (SELECT M.B INTERSECT SELECT T.B)
_
NUMERIC
へのキャストは、整数除算を回避するためにあります。結合句の理由は ここで説明 です。
必要に応じて、ON M.B = T.B OR (M.B IS NULL AND T.B IS NULL)
に置き換えることができます(または、B
列がnullにできない場合は、単に_ON M.B = T.B
_に置き換えることができます)。
これにより、Bで分割されたAの個別のカウント(*)が得られます。
dense_rank() over (partition by B order by A)
+ dense_rank() over (partition by B order by A desc)
- 1
dense_rank()
の最大値を取得して、Bで分割されたAの個別のカウントを取得できます。
Aがnull値を持つ可能性がある場合に対処するには、first_value
を使用して、パーティションにnullが存在するかどうかを判断し、Martin Smithのコメントで示唆されている場合は1を減算します。
select (max(T.DenseRankA) over(partition by T.B) -
cast(iif(T.FirstA is null, 1, 0) as numeric(18, 8))) / T.TotalCount as A_B
from (
select dense_rank() over(partition by T.B order by T.A) DenseRankA,
first_value(T.A) over(partition by T.B order by T.A) as FirstA,
count(*) over() as TotalCount,
T.A,
T.B
from MyTable as T
) as T
サブクエリを実行して、A、Bでグループ化し、カウントを含めてみてください。次に、外部クエリで、count(distinct)は通常のカウントになり、count(*)はsum(cnt)になります。
select
count(A) over (partition by B) * 1.0 /
sum(cnt) over() as A_B
from
(select A, B, count(*) as cnt
from MyTable
group by A, B) as partial;
今のところSQL Serverでは、ウィンドウ関数でDistinct
を使用することはできません。
しかし、ウィンドウ関数がどのように機能するか(つまり、それらがクエリの結果セットに適用されること)を思い出したら、次のように対処できます。
select B,
min(count(distinct A)) over (partition by B) / max(count(*)) over() as A_B
from MyTable
group by B