SQL Server:PARTITION BYとGROUP BYの違い


366

私はGROUP BY何年にもわたってすべてのタイプの集約照会に使用してきました。最近、私はPARTITION BY集計を実行するために使用するいくつかのコードをリバースエンジニアリングしています。私が見つけることができるすべてのドキュメントを読むとPARTITION BY、それはに似ているようですがGROUP BY、おそらく追加の機能が少し追加されていますか?それらは同じ一般的な機能の2つのバージョンですか、それとも完全に異なるものですか?

回答:


441

彼らはさまざまな場所で使用されています。 group by次のようにクエリ全体を変更します。

select customerId, count(*) as orderCount
from Orders
group by customerId

しかし、次のようなウィンドウ関数partition by動作しますrow_number

select row_number() over (partition by customerId order by orderId)
    as OrderNumberForThisCustomer
from Orders

Aは、group by通常、それらをロールアップし、行ごとに平均又は合計を計算することによって返される行の数を減少させます。 partition by返される行数には影響しませんが、ウィンドウ関数の結果の計算方法を変更します。


23
いい答えです。それぞれに返された結果のサンプルを書いていただけませんか。
Ashkan Mobayen Khiabani 2013年

2
@AshkanMobayenKhiabaniでは、Northwindに対して両方のクエリを実行できます。これは、SQLサーバーのバージョンに応じて、デフォルトでインストールされる場合とインストールされない場合があります。そうでない場合は、ダウンロードページで検索できます。
Fetchez la vache

15
以下の@AshkanMobayenKhiabani Arunprasanthの回答は、返された結果を示しています。これにより、より多くの学習フープを飛び越えてNorthwindを学ぶ時間とは対照的に、時間を節約できます
Praxiteles

1
もっと(SQLで)窓関数の:blog.jooq.org/2013/11/03/...
datps

itcodehub.blogspot.com/2019/03/…-SQLでのgroup byとpartition byの違いに関する詳細と例
xproph

252

簡単な例を挙げることができます。

TableA次の値で名前が付けられたテーブルを考えます。

id  firstname                   lastname                    Mark
-------------------------------------------------------------------
1   arun                        prasanth                    40
2   ann                         antony                      45
3   sruthy                      abc                         41
6   new                         abc                         47
1   arun                        prasanth                    45
1   arun                        prasanth                    49
2   ann                         antony                      49

GROUP BY

SQL GROUP BY句をSELECTステートメントで使用して、複数のレコードにわたるデータを収集し、結果を1つ以上の列でグループ化できます。

より簡単に言えば、GROUP BYステートメントは、1つ以上の列によって結果セットをグループ化するために、集計関数と組み合わせて使用​​されます。

構文:

SELECT expression1, expression2, ... expression_n, 
       aggregate_function (aggregate_expression)
FROM tables
WHERE conditions
GROUP BY expression1, expression2, ... expression_n;

GROUP BYテーブルに適用できます:

select SUM(Mark)marksum,firstname from TableA
group by id,firstName

結果:

marksum  firstname
----------------
94      ann                      
134     arun                     
47      new                      
41      sruthy   

実際のテーブルには7つの行があり、を適用するGROUP BY idと、サーバーグループに基づいて結果がグループ化されidます。

簡単な言葉で:

ここでGROUP BYは通常、それらをロールアップSum()して各行について計算することにより、返される行の数を減らします。

PARTITION BY

PARTITION BYに進む前に、OVER句を見てみましょう。

MSDNの定義によると:

OVER句は、クエリ結果セット内のウィンドウまたはユーザー指定の行セットを定義します。次に、ウィンドウ関数がウィンドウの各行の値を計算します。関数でOVER句を使用して、移動平均、累積集計、累計、グループごとの上位Nなどの集計値を計算できます。

PARTITION BYは、返される行の数を減らしません。

サンプルテーブルでPARTITION BYを適用できます。

SELECT SUM(Mark) OVER (PARTITION BY id) AS marksum, firstname FROM TableA

結果:

marksum firstname 
-------------------
134     arun                     
134     arun                     
134     arun                     
94      ann                      
94      ann                      
41      sruthy                   
47      new  

結果を見てください-GROUP BYとは異なり、行を分割してすべての行を返します。


3
partition by 行数に影響を与える可能性がありますが、行数は減りません。
ジョン

1
私が変更した場合の違いは何でしょうSELECTにと SELECT DISTINCT2番目のクエリに?それはGROUP BYクエリと同じデータセットを返さないでしょうか?どちらか一方を選択する理由は何ですか?
エリック3E 2017

3
@ Erick3Eこの質問の上を見ていてくださいstackoverflow.com/questions/20375074/...を
Arunprasanth KV

パーティションで集計関数の最小/最大/合計などがどのように機能するかを示しているので、私はこの答えがより好きです。Row_Number()の例では、それほど明確ではありません。通常、私はGROUP BYで集約関数を使用していますが、PARTITION-OVERが同じメソッドを持っていることに気づき、OPが行ったのと同じことを不思議に思いました。ありがとう!
ripvlan

53

partition by実際にはデータをロールアップしません。グループごとに何かをリセットできます。たとえば、グループ化フィールドでパーティション化し、rownum()そのグループ内の行に対して使用することにより、グループ内の序列を取得できます。これにより、各グループの先頭でリセットされるID列のように動作するものが得られます。


43

PARTITION BY結果セットをパーティションに分割します。ウィンドウ関数は各パーティションに個別に適用され、各パーティションの計算が再開されます。

このリンクで見つかりました:OVER句


36

ロールアップせずにロールアップされたデータを提供します

つまり、販売地域の相対的な位置を返したいとしましょう。

PARTITIONのBYを使用して、Iは、所与の領域の販売量を返すことができる同じ列内のすべての販売地域を横断MAX量。

これは繰り返しデータがあることを意味しますが、データは集約されているがデータが失われていないという意味では、エンドユーザーに適している可能性があります-GROUP BYの場合と同様です。


3
最良の最も簡単な答え。
tmthyjames

27

PARTITION BYは分析的ですが、GROUP BY集約的です。使用するにはPARTITION BYOVER句を使用してそれを含める必要があります。


1
PARTITION BY is analyticこの単純な発言は私にとってかなり明確になりました。+1。

これは実際には最も単純で最良の答えです。
jdmneon

22

私の理解では、Partition ByはGroup Byとほとんど同じですが、次の違いがあります。

そのグループは、グループごとに1行を返す結果セットを実際にグループ化します。その結果、SQL Serverでは、SELECTリストで、group by句の一部である集計関数または列のみを許可します(この場合、SQL Serverは一意であることを保証できます。各グループの結果)。

たとえば、MySQLで、Group By句で定義されていない列をSELECTリストに含めることができます。この場合、グループごとに1行が返されますが、列に一意の結果がない場合、保証はありません。何が出力されます!

しかし、Partition Byを使用すると、関数の結果はGroup Byを使用した集計関数の結果と同じですが、通常の結果セットが得られます。つまり、基になる行ごとに1行ではなく、1行ごとに1行取得されます。これにより、SELECTリスト内のグループごとに一意ではない列を含めることができます。

したがって、要約として、グループ化はグループごとに1行の出力が必要な場合に最適であり、パーティション化はすべての行が必要だがグループに基づく集計関数が必要な場合に最適です。

もちろん、パフォーマンスの問題もある可能性があります。http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fbaを参照してください


2

を使用するGROUP BYと、通常、結果の行は入力行よりも少なくなります。

ただし、を使用するPARTITION BYと、結果の行数は着信と同じになります。


0

nameテーブルに14レコードの列があるとします。

group by

select name,count(*) as totalcount from person where name='Please fill out' group BY name;

単一の行、つまり14でカウントされます

でも partition by

select row_number() over (partition by name) as total from person where name = 'Please fill out';

カウントが14行増加します


0

小さな観察。「partition by」を使用してSQLを動的に生成する自動化メカニズムは、「group by」に関連して実装する方がはるかに簡単です。「グループ化」の場合、「選択」列の内容に注意する必要があります。

私の英語でごめんなさい。


0

それは本当に異なる使用シナリオを持っています。GROUP BYを使用すると、同じ列の一部のレコードをマージし、結果セットの集計ができます。

ただし、PARTITION BYを使用しても結果セットは同じですが、ウィンドウ関数に対する集計があり、レコードをマージしない場合でも、同じレコード数になります。

これは違いを説明するラリーに役立つ記事です:http : //alevryustemov.com/sql/sql-partition-by/


-1
-- BELOW IS A SAMPLE WHICH OUTLINES THE SIMPLE DIFFERENCES
-- READ IT AND THEN EXECUTE IT
-- THERE ARE THREE ROWS OF EACH COLOR INSERTED INTO THE TABLE
-- CREATE A database called testDB


-- use testDB
USE [TestDB]
GO


-- create Paints table
CREATE TABLE [dbo].[Paints](
    [Color] [varchar](50) NULL,
    [glossLevel] [varchar](50) NULL
) ON [PRIMARY]

GO


-- Populate Table
insert into paints (color, glossLevel)
select 'red', 'eggshell'
union
select 'red', 'glossy'
union
select 'red', 'flat'
union
select 'blue', 'eggshell'
union
select 'blue', 'glossy'
union
select 'blue', 'flat'
union
select 'orange', 'glossy'
union
select 'orange', 'flat'
union
select 'orange', 'eggshell'
union
select 'green', 'eggshell'
union
select 'green', 'glossy'
union
select 'green', 'flat'
union
select 'black', 'eggshell'
union
select 'black', 'glossy'
union
select 'black', 'flat'
union
select 'purple', 'eggshell'
union
select 'purple', 'glossy'
union
select 'purple', 'flat'
union
select 'salmon', 'eggshell'
union
select 'salmon', 'glossy'
union
select 'salmon', 'flat'


/*   COMPARE 'GROUP BY' color to 'OVER (PARTITION BY Color)'  */

-- GROUP BY Color 
-- row quantity defined by group by
-- aggregate (count(*)) defined by group by
select count(*) from paints
group by color

-- OVER (PARTITION BY... Color 
-- row quantity defined by main query
-- aggregate defined by OVER-PARTITION BY
select color
, glossLevel
, count(*) OVER (Partition by color)
from paints

/* COMPARE 'GROUP BY' color, glossLevel to 'OVER (PARTITION BY Color, GlossLevel)'  */

-- GROUP BY Color, GlossLevel
-- row quantity defined by GROUP BY
-- aggregate (count(*)) defined by GROUP BY
select count(*) from paints
group by color, glossLevel



-- Partition by Color, GlossLevel
-- row quantity defined by main query
-- aggregate (count(*)) defined by OVER-PARTITION BY
select color
, glossLevel
, count(*) OVER (Partition by color, glossLevel)
from paints
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.