私は長年GROUP BY
にわたり、あらゆる種類の集計クエリに使用してきました。PARTITION BY
最近、集計の実行に使用するコードのリバース エンジニアリングを行っています。について見つけることができるすべてのドキュメントを読むPARTITION BY
と、 によく似ているように聞こえますがGROUP BY
、少し追加の機能が追加されているのではないでしょうか? それらは同じ一般的な機能の 2 つのバージョンですか、それともまったく異なるものですか?
13 に答える
いろいろなところで使われています。 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
はgroup by
通常、返される行数をロールアップして各行の平均または合計を計算することで減らします。 partition by
返される行数には影響しませんが、ウィンドウ関数の結果の計算方法が変わります。
簡単な例を挙げることができます。
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
OVER
PARTITION BY に行く前に、句を見てみましょう。
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 とは異なり、行が分割され、すべての行が返されます。
partition by
実際にはデータをロールアップしません。グループごとに何かをリセットできます。たとえば、グループ化フィールドで分割し、そのグループrownum()
内の行に対して使用することで、グループ内の序数列を取得できます。これにより、各グループの開始時にリセットされる ID 列に少し似た動作が得られます。
PARTITION BY 結果セットをパーティションに分割します。ウィンドウ関数は各パーティションに個別に適用され、各パーティションで計算が再開されます。
このリンクにあります: OVER句
ロールアップせずにロールアップされたデータを提供します
つまり、販売地域の相対位置を返したいとします
PARTITION BY を使用すると、特定の地域の売上高と、すべての売上地域の MAX 金額を同じ行で返すことができます。
これは繰り返しデータを持つことを意味しますが、GROUP BY の場合のように、データが集約されているがデータが失われていないという意味で、最終消費者に適している可能性があります。
PARTITION BY
は分析的ですが、GROUP BY
は集計です。使用するには、 OVER 句PARTITION BY
で含める必要があります。
私の理解では、Partition By は Group By とほぼ同じですが、次の違いがあります。
その group by は、実際にはグループごとに 1 つの行を返す結果セットをグループ化します。したがって、SQL Server では、group by 句の一部である SELECT リストの集計関数または列のみが許可されます (この場合、SQL Server は、一意の行があることを保証できます)。各グループの結果)。
たとえば、Group By 句で定義されていない列を SELECT リストに含めることを許可する MySQL を考えてみましょう。この場合、グループごとに 1 つの行が返されますが、列に一意の結果がない場合は保証されません。出力はどうなりますか!
ただし、Partition By を使用すると、関数の結果は Group By を使用した集計関数の結果と同じですが、通常の結果セットが得られます。このため、SELECT リスト内のグループごとに一意ではない列を持つことができます。
要約すると、グループごとに 1 行の出力が必要な場合は Group By が最適であり、すべての行が必要であるがグループに基づく集計関数が必要な場合は Partition By が最適です。
もちろん、パフォーマンスの問題もあるかもしれません。
name
テーブルに列の 14 レコードがあるとします。
のgroup by
select name,count(*) as totalcount from person where name='Please fill out' group BY name;
1行、つまり14でカウントされます
しかしpartition by
select row_number() over (partition by name) as total from person where name = 'Please fill out';
カウントが14行増加します
-- 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