この記事では、SQL PARTITION BY句をいつどのように使用するかを調べ、GROUPBY句を使用する場合と比較します。
データベースユーザーは、MAX()、MIN()、AVERAGE()、COUNT()などの集計関数を使用してデータ分析を実行します。これらの関数はテーブル全体を操作し、GROUPBY句を使用して単一の集計データを返します。場合によっては、小さな行セットに集約された値が必要になります。この場合、集約関数と組み合わせたウィンドウ関数は、目的の出力を実現するのに役立ちます。 Window関数はOVER()句を使用し、次の関数を含めることができます。
- パーティション作成者: これにより、行またはクエリ結果セットが小さなパーティションに分割されます。
- 注文者: これにより、パーティションウィンドウの行が昇順または降順で配置されます。デフォルトの順序は昇順です。
- 行または範囲: 開始点と終了点を指定することで、パーティション内の行をさらに制限できます。
この記事では、SQLPARTITIONBY句の調査に焦点を当てます。
顧客の注文の詳細を格納するテーブル[SalesLT]。[Orders]があるとします。注文が行われた顧客の都市を指定する[City]列があります。
CREATE TABLE [SalesLT].[Orders] ( orderid INT, orderdate DATE, customerName VARCHAR(100), City VARCHAR(50), amount MONEY ) INSERT INTO [SalesLT].[Orders] SELECT 1,'01/01/2021','Mohan Gupta','Alwar',10000 UNION ALL SELECT 2,'02/04/2021','Lucky Ali','Kota',20000 UNION ALL SELECT 3,'03/02/2021','Raj Kumar','Jaipur',5000 UNION ALL SELECT 4,'04/02/2021','Jyoti Kumari','Jaipur',15000 UNION ALL SELECT 5,'05/03/2021','Rahul Gupta','Jaipur',7000 UNION ALL SELECT 6,'06/04/2021','Mohan Kumar','Alwar',25000 UNION ALL SELECT 7,'07/02/2021','Kashish Agarwal','Alwar',15000 UNION ALL SELECT 8,'08/03/2021','Nagar Singh','Kota',2000 UNION ALL SELECT 9,'09/04/2021','Anil KG','Alwar',1000 Go
場所(都市)ごとの合計注文額を知りたいとします。この目的のために、以下に示すようにSUM()およびGROUPBY関数を使用します。
SELECT City AS CustomerCity ,sum(amount) AS totalamount FROM [SalesLT].[Orders] GROUP BY city ORDER BY city
結果セットでは、SELECTステートメントで集計されていない列を使用することはできません。たとえば、[CustomerName]はGROUP BY句に含まれていないため、出力に表示できません。
列リストで集計されていない列を使用しようとすると、SQLServerは次のエラーメッセージを表示します。
SELECT City AS CustomerCity, CustomerName,amount, SUM(amount) OVER(PARTITION BY city) TotalOrderAmount FROM [SalesLT].[Orders]
以下に示すように、PARTITION BY句は、より小さなウィンドウ(データ行のセット)を作成し、集計を実行して表示します。この出力では、集計されていない列も表示できます。
同様に、関数AVG()、MIN()、MAX()を使用して、ウィンドウ内の行から平均、最小、および最大量を計算できます。
SELECT City AS CustomerCity, CustomerName,amount, SUM(amount) OVER(PARTITION BY city) TotalOrderAmount, Avg(amount) OVER(PARTITION BY city) AvgOrderAmount, Min(amount) OVER(PARTITION BY city) MinOrderAmount, MAX(amount) OVER(PARTITION BY city) MaxOrderAmount FROM [SalesLT].[Orders]
SQL PARTITION BY句をROW_NUMBER()関数で使用する
以前は、PARTITIONBY句を使用してウィンドウに集計値を取得していました。合計ではなく、パーティション内の累積合計が必要であるとします。
累積合計は次のように機能します。
1 |
2 |
3 |
行ランクは、関数ROW_NUMBER()を使用して計算されます。まず、この関数を使用して、行のランクを表示しましょう。
- ROW_NUMBER()関数は、OVER句とPARTITION BY句を使用して、結果を昇順または降順で並べ替えます。並べ替え順序ごとに1から行のランク付けを開始します。
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number] FROM [SalesLT].[Orders]
たとえば、[Alwar]市では、金額が最も多い行(25000.00)が行1にあります。次に示すように、PARTITIONBY句で指定されたウィンドウの行をランク付けします。たとえば、[Alwar]、[Jaipur]、[Kota]の3つの異なる都市があり、各ウィンドウ(都市)はその行ランクを取得します。
累積合計を計算するには、次の引数を使用します。
- 現在の行:指定された範囲の開始点と終了点を指定します。
- 1次:現在の行から続く行数(1)を指定します。
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number], SUM(amount) OVER(PARTITION BY city ORDER BY amount DESC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS CumulativeSUM FROM [SalesLT].[Orders]
次の画像は、PARTITIONBY句で指定されたウィンドウで全体の合計ではなく累積の合計を取得することを示しています。
ROWSUNBOUNDEDPRECEDINGを使用する場合 SQL PARTITION BY句では、次の方法で累積合計を計算します。現在の行と、指定されたウィンドウで最も高い値を持つ行を使用します。
1 |
2 |
3 |
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number], SUM(amount) OVER(PARTITION BY city ORDER BY amount DESC ROWS UNBOUNDED PRECEDING) AS CumulativeSUM FROM [SalesLT].[Orders]
GROUPBY句とSQLPARTITIONBY句の比較
集計値を計算した後、グループごとに1行を返します。 | SELECTステートメントのすべての行と、集計値の追加の列を返します。 |
SELECTステートメントで非集計列を使用することはできません。 | SELECTステートメントで必須の列を使用でき、集計されていない列に対してエラーは発生しません。 |
SELECTステートメントからレコードをフィルタリングするには、HAVING句を使用する必要があります。 | PARTITION関数は、SELECTステートメントで使用される列とは別に、WHERE句に追加の述語を含めることができます。 |
GROUPBYは通常の集計で使用されます。 | PARTITIONBYはウィンドウアグリゲートで使用されます。 |
個々のグループの集計値に対して複数のデータグループを操作する場合は、SQLPARTITIONBY句を使用することをお勧めします。同様に、集計値の列が追加された元の行を表示するために使用できます。