27

group by句でウィンドウ関数を使用できない理由と、SELECTおよびでのみ許可されている理由を誰かが説明できますかORDER BY

row_number()次のように、SQL Server の列に基づいてレコードをグループ化しようとしていました。

SELECT Invoice
from table1
group by row_number() over(order by Invoice),Invoice

エラーが発生します

ウィンドウ関数は、SELECT または ORDER BY でのみ使用できます。

これrow_number()は SELECT 句で選択できますが、group by で使用できない理由を知りたいですか?

4

2 に答える 2

20

ウィンドウ関数は ANSI 仕様で定義されており、 、 、 の処理後に論理的に実行さGROUP BYHAVINGますWHERE

具体的には、こちらの論理クエリ処理フロー チャートのステップ 5.1 と 6 で許可されています。

彼らはそれを別の方法で定義し、そのフェーズの開始時にウィンドウが論理結果セットであるウィンドウ関数を使用することを許可できたと思いますが、それらがあり、次のようなクエリを作成することが許可されたとしGROUP BYますWHEREHAVING

SELECT a, 
       b, 
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect
  FROM YourTable
  WHERE NTILE(2) OVER (PARTITION BY a ORDER BY b) > 1
  GROUP BY a, 
           b, 
           NTILE(2) OVER (PARTITION BY a ORDER BY b)
  HAVING NTILE(2) OVER (PARTITION BY a ORDER BY b) = 1

4 つの異なる論理ウィンドウを使用して、この結果がどうなるかを考えてみてください。また、の後の結果である行のウィンドウではなく、上HAVINGのレベルからの式で実際にフィルタリングしたい場合はどうなりますか?GROUP BYGROUP BY

CTE バージョンはより冗長ですが、より明示的で従いやすくなっています。

WITH T1 AS
(
SELECT a, 
       b, 
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForWhere
  FROM YourTable
), T2 AS
(
SELECT a,
       b,
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForGroupBy
FROM T1
WHERE NtileForWhere > 1
), T3 AS
(
SELECT a,
       b,
       NtileForGroupBy,
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForHaving
FROM T2
GROUP BY a,b, NtileForGroupBy
)
SELECT a,
       b,
       NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect
FROM T3
WHERE NtileForHaving = 1

これらはすべてSELECTステートメントで定義され、エイリアスが付けられているため、さまざまなレベルからの結果を簡単に明確にすることができます。たとえば、単純に切り替えるだけですWHERE NtileForHaving = 1NtileForGroupBy = 1

于 2013-01-01T21:44:30.877 に答える