Redgate Hub

  1. え? SQLでSET、CUBE、ROLLUPをグループ化するとは何ですか?なぜROLLUPやCUBEが私にとって役に立つのでしょうか?
  2. これらの標準SQLはありますか、それともMicrosoft専用のものですか?
  3. ロールアップから1つ以上の列を除外できますか?
  4. グループ化セットとは何ですか? 私はそれらについて知っておくべきですか?
  5. なぜ集計で列を結合したいのですか?
  6. グループ化セットには、”アラカルト”キューブを行う方法よりも多くのものがありますか?
  7. 関数Grouping()とGrouping_Id()が提供されているのはなぜですか?

え? SQLでSET、CUBE、ROLLUPをグループ化するとは何ですか?

CUBE、ROLLUP、およびGROUPING SETは、大量の情報を含むレポートを実行するためのSELECTステートメントのGROUP BY句のオプションの演算子です。 これにより、1つの文で複数のGROUP BY操作を実行できるため、多くの時間と計算労力を節約できます。 合計を含むレポートに必要なすべての情報を提供しながら、大きなテーブルに対して優れたパフォーマンスを提供し、クエリオプティマイザが適切な実行余分な’super-aggregate’行は要約値を提供するため、1つの結果の中にSUM()やMAX()などのいくつかの’集計’を含めることができます。 結果のこれらの行内のNullは、’unknown’ではなく’all’を意味することを意図しています。 これにより、テーブルを1回のパスで必要なすべての集計を取得できます。 結果に余分な行が存在するため、余分な関数GROUPING()GROUPING_ID()は、これらの余分な”スーパー集計”行と集計されている列を示すために提供され

余分な計算をせずに、またはデータベースに戻らずに複数のレポートを実行する必要があるアプリケーションがある場合、これは非常に意味があります。この標準的なロールアップの例を取ります(ここではAdventureWorks2012を使用しています)。.

1
2
3
4
5

となっています。div>6

を選択。 として地域。名として領域内にて、和(TotalDue)として収益、
datepart(yyyy,OrderDate)としては、datepart(mm、OrderDateとして
からの販売です。SalesOrderHeader s
内部結合売上高。SalesTerritory T ON S.TerritoryID=T.TerritoryID
Tによるグループ化。,t.name,datepart(yyyy,OrderDate),datepart(mm,OrderDate)
WITH ROLLUP

単純なグループ化で得られる毎月の合計期日を持つ単純なGROUP BY aggregate行と同様に、小計または超集約行、およ (ここでは結果の始まりです)

2303-clip_image001。png

私が強調したNULLは、行がフランス(ヨーロッパ地域の一部)の2005年の”すべての”月の集計であることを意味します

これだけでなく、各年の合計、各テリ (最後から)

2303-clip_image002。png

これらのNullは’すべて’を意味します。 最後の行は総計であり、その上には太平洋地域の合計があります。 その上には、太平洋地域へのオーストラリアの貢献があります。 下から4番目の列はオーストラリアの2008年の貢献です。 返されるグループ化の数は、GROUP BY文に指定された複合要素リスト内の式の数よりも1つ多くなります。 ロールアップを使用せずに同じ効果を得るには、次のようなことを行う必要があります(Adventureworks2012)

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
19
19
19
19
19
19
19
19
19
19
19
19>
;

とmyGrouping(region,territory,totalDue,,)
として(tを選択します。,t.name、合計(TotalDue)収益として、
datepart(yyyy、OrderDate)として、Datepart(mm、OrderDate)として
売上高から。SalesOrderHeader s
内部結合売上高。SalesTerritory T ON s.TerritoryID=T.TerritoryID
グループ化t.name,t.、datepart(yyyy,OrderDate)、datepart(mm,OrderDate))
地域、領土、合計(totalDue)を選択します,,
MYGROUPINGから
すべての連合
地域、領土、合計(totalDue)を選択します,,NULL
myGroupingから地域、領土、合計(totalDue)を選択します,,NULL
地域、領土、合計(totalDue)を選択します
すべての連合
地域、領土、合計(totalDue)を選択します
null、null
からMygrouping地域別グループ、テリトリー
union ALL
select region,null,sum(totaldue),null,null
from mygrouping地域別グループ
union all
nullを選択します, NULL, sum(totalDue), NULL, NULL
FROM myGrouping

Which is a lot more expensive in CPU and I/O. Note that the standard syntax of the GROUP BY clause in recent versions is

1
2

‘GROUPBY ROLLUP (t.,t.

この新しい構文を使用すると、いくつかの追加機能が可能になります。 列の順序はROLLUPの出力グループに影響し、結果セット内の行数に影響する可能性があることにも注意してください。

キューブは同じ一般的なことを行いますが、順序付けられた超集約行に合計の階層を提供する代わりに、すべての’超集約’順列(’対称超集約’行)、いわゆる あなたは月に最も注文を与えた領土、または2006年に最もうまく機能しなかった領土を知りたい場合は、キューブが必要になります。 あなたは結果にすべての可能な合計を提供しています。

GROUPING SETを使用すると、結果を微調整して、CUBEを超えてより専門的な情報を提供することができます。 これは、寸法の組み合わせに関する要約情報を提供することができます。 グループ化セットを使用することで、ロールアップの例とまったく同じ結果を得ることができますが、より多くの入力を行うことができます。

1
2
3
4
5

となっています。div>6

7
8
9
10
を選択。 として地域。名として領域内にて、和(TotalDue)として収益、
datepart(yyyy,OrderDate)としては、datepart(mm、OrderDateとして
からの販売です。SalesOrderHeader s
内部結合売上高。S.TerritoryID=TのSalesTerritory T。TerritoryID
グループ化セットによるグループ化(
(T.,T.nameこれを行うには、次の手順を実行します。T.nameこれを行うには、次の手順を実行します。T.nameこれは、それらがどのように関連しているかを示すためだけです。 実際には、ROLLUPまたはCUBEでは不可能な結果を得るためにセットをグループ化することに頼っています。

ほとんどすべてのこれらの要約は、GROUP BYだけを使用することから得ることができますが、GROUP BYの結果を繰り返しグループ化するか、データを複数回通過させることによってのみ得ることができます。CUBE、ROLLUP、またはGROUPING SETSを使用している場合、AVG(DISTINCT column_name)、COUNT(DISTINCT column_name)、SUM(DISTINCT column_name)などの集計式でDISTINCTキーワードを使用することはできません。

ROLLUPまたはCUBEは私に役立ロールアップとキューブは、SSASの前に全盛期を持っていました。

それらはOLAPの立方体によって提供される同じ種類の設備を提供するために有用だった。 それはまだその用途を持っています。 AdventureWorksでは、やりすぎですが、大量のデータを処理する場合は、データを一度だけ渡し、集計されたデータに対して可能な限り処理する必要があります。 過去に発生したイベントは変更できないため、アクティブなOLTPシステムに履歴データを保持する必要はほとんどありません。 代わりに、すべての予測可能なレポートに必要な詳細レベル(”粒度”)で集計データを保持する必要があります。

あなたが一日に二百万かそこらの呼び出しを持っている電話スイッチに報告する責任があると想像してみてください。 OLTPサーバーでこれらの呼び出しをすべて保持すると、すぐに使用状況レポートを処理するSQL Serverが見つかります。 あなたは法定期間のために元のコール情報を保持する必要がありますが、あなたは彼らが、せいぜい、分でのコールの数にのみ興味を持っていることをビ 次に、OLTPサーバーのストレージ要件を1に減らしました。それが何であったかの4%、およびコールレコードは、アドホッククエリと顧客ステートメントのために別のSQL Serverにアーカイブすることができます。 それは価値のある節約になる可能性があります。 CUBE句とROLLUP句を使用すると、集計テーブルのテーブルまたはクラスター化インデックスのスキャンを実行せずに、行の合計、列の合計、および総計を格納する

このデータに遡及的に変更が加えられず、すべての期間が完了している限り、過去の期間に基づいて集計を繰り返したり変更したりする必要はあ.

ふりをしましょうが、Adventureworks2012を使用して遊ぶことができます。

まず、gram summaryテーブルを作成します。

1
2
3
4
5

となっています。div>6

7
8
9
10
11
12
13
14
15
16
17
18
19
が存在する(SELECT*from tempdb.シスオ…テーブルwhere name LIKE’#AggregationTable%’)
DROP TABLE#aggregationTable–一時テーブルが存在する場合は削除します
GO
SELECT
identity(INT,1,1)AS,–一意の列を持つことができます
t。t.name たとえば、次のようにします。

t.name)isNameGroupとして、-これはすべてのテリトリーに関連していますか

grouping(t.)IsGroupGroupとして、-これはすべての大陸に関連していますか
grouping(datepart(yyyy,OrderDate))as isYearGroup、-これはすべての年に関連していますか
grouping(datepart(mm,OrderDate))as isMonthGroup、-これはすべての月に関連していますか
Grouping_Id(t.nameこれは、集計データを含む余分な非データ行ですか
INTO#AggregationTable
Salesから。SalesOrderHeader s
内部結合売上高。S.TerritoryID=TのSalesTerritory T。
グループ化する
グループ化する
グループ化t.name,t.,datepart(yyyy,OrderDate),datepart(mm,OrderDate)
WITH ROLLUP

要約行を含む行を示す余分な”ビット”列を追加していることに注意してください。 あなたが誤ってそれ以上の集計にそれらを追加すると、いくつかの真剣に膨張した結果が得られます。 保存された結果にGrouping()またはGrouping_Idを使用することはできないので、代わりに何かを提供する必要があります。これで、ピボットテーブルを非常に高速に生成できます

2303-clip_image004.jpg2303-CLIP_IMAGE004.jpg

だから、これを見てマネージャーから簡単な笑顔がありますが、その後、彼らは明るく”私はまた、月ごとの領土別の内訳を求めていると確信しています

簡単な笑いで、あなたはこれを行います。

1
2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
19
19
19
19
19
19
19
19
19
19
19
19div>18
19
–行と
–列の合計
select territory,
sum(CASE WHEN2005then revenue ELSE0END)AS,
sum(CASE WHEN2006THEN revenue ELSE0END)AS,
sum(CASE WHEN2007then revenue ELSE0END)AS,
sum(CASE WHEN2008then revenue ELSE0END)AS,
sum(revenue)AS
FROM#AggregationTable
WHERE isGroupingrow=0
テリトリーによるグループ化
union all
SELECT’TOTAL’,SUM(case WHEN2005then revenue else0end)as,
SUM(case WHEN2006then revenue else0end)as,
SUM(case WHEN2007then revenue else0end)as,
SUM(case WHEN2006then revenue else0end)as,
SUM(case WHEN2007then revenue else0end)as,
SUM(case WHEN2007then revenue else0end) ,
1
2
3
4
5

となっています。div>6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26日
27
28日
29日
30

となっています。div>31日

32
SELECT
datename(MONTH,dateadd(MONTH,,’01dec2000′))AS,
sum(CASE territory WHEN’Australia’THEN revenue ELSE0END)AS,
sum(CASE Territory WHEN’Canada’THEN revenue ELSE0END)as,
sum(CASE Territory WHEN’Canada’then revenue ELSE0END)as,
sum(CASE Territory WHEN’Central’then revenue ELSE0END)AS,
sum(CASE Territory WHEN’Central’THEN revenue ELSE0END)AS,
sum(CASE Territory WHEN’Central’THEN revenue ELSE0END)AS,
div>

sum(case territory when’france’then revenue else0end)as,
sum(case territory when’germany’then revenue else0end)as,
sum(CASE territory when’northeast’then revenue else0end)AS,
SUM(CASE territory when’northeast’then revenue else0end)AS,
SUM(CASE territory when’northeast’then revenue else0end)AS Div>

sum(case territory WHEN’Southeast’THEN revenue ELSE0END)AS,
sum(CASE territory WHEN’Southeast’then revenue ELSE0END)AS,
sum(CASE Territory WHEN’Southeast’then revenue ELSE0END)as,
sum(case Territory WHEN’United Kingdom’THEN revenue ELSE0END)AS,
sum(revenue)AS
FROM#AggregationTable
WHERE isGroupingrow=0
月によるグループ化
union all
select
‘TOTAL’,
sum(case TERRITORY when’australia’then REVENUE else0END)AS,
sum(case TERRITORY when’australia’then REVENUE else0END)AS,
sum(case TERRITORY when’australia’THEN REVENUE else0END)AS,
sum Div>

sum(case territory WHEN’Central’THEN revenue ELSE0END)AS,
sum(CASE territory WHEN’Central’THEN revenue ELSE0END)as,
sum(CASE territory WHEN’France’THEN revenue ELSE0END)AS,
sum(CASE territory WHEN’Germany’THEN revenue ELSE0END)AS,
sum(CASE Territory WHEN’Northeast’then revenue ELSE0END)as,
sum(CASE Territory WHEN’Northeast’THEN revenue ELSE0END)as,
sum(CASE Territory WHEN’Northeast’THEN revenue ELSE0END)AS,
sum(CASE Territory WHEN’Northeast’THEN revenue ELSE0END)AS,DIV>

SUM(case territory when’southeast’then revenue else0end)as,
SUM(CASE territory when’southeast’then revenue else0end)as,

2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-2303-clip_image005.しかし、Rollupの代わりにCUBEを使用した場合、その最後の'total'行はすでに計算されます。 実際の例では、レポートを実行するのに時間がかかります。 それらは集計を一括する傾向がありますが、あまりにも高価ではありません。これらの標準SQLはありますか、それともMicrosoft専用のものですか?これらは1999年から標準ANSI SQLになりましたが、WITH CUBEとWITH ROLLUPはMicrosoftによって最初に導入されました。 この包含は、'unknown'以外のNULL値に'all'という2番目の意味を導入するという点でやや驚くべきことです。 Microsoftが最初にCUBEとROLLUPを導入したとき、構文はわずかに異なりましたが、SQL Serverでは両方の形式が許可されています。 単一のSELECT文で使用できる構文スタイルは1つだけであり、すべての新しい作業にISO準拠の構文を使用する必要があります。ロールアップから1つ以上の列を除外できますか?あなたがしたい場合は!

あなたがしたい場合は!

私はすべての地域のための超集約合計を望んでいなかったことを想像してみてください(t。)

1
2

3

4
5
6
t.name テリトリーとして、sum(TotalDue)収益として、Datepart(yyyy,OrderDate)として、Datepart(mm,OrderDate)として

売上高から。SalesOrderHeader s
内部結合売上高。SalesTerritory T ON S.TerritoryID=T.TerritoryID
Tによるグループ化。,ROLLUP(t.nameここでは、ANSI SQL2006準拠の構文を使用しています。 あなたは立方体で同じことをすることができます。 私はこれの実用的な使用法を見つけたことはありませんが、あなたはそれに出くわすかもしれません

グループ化セットは何ですか? 私はそれらについて知っておくべきですか?グループ化セットは、結果を数回グループ化するようにSQLに要求していることを意味します。 GROUPING SETS構文を使用すると、計算する集計を正確に指定できます。 ここに例があります。

1
2
3
4
5

となっています。div>6

を選択。 として地域。名として領域内にて、和(TotalDue)として収益、
datepart(yyyy,OrderDate)としては、datepart(mm、OrderDateとして
からの販売です。SalesOrderHeader s
内部結合売上高。Sの販売代理店T.TerritoryID=T.TerritoryID
Tによるグループ化。,グループ化セット(ROLLUP(t.nameここでは、毎月のテリトリーグループ別の内訳を求めています月と年の合計、その後にテリトリー名による要約合計が続きますが、総計はありません。 ロールアップとは異なり、各グループ化セット内の列の順序とグループ化セットの順序にかかわらず、同じ結果が得られます。

グループ化セットは、CUBEとROLLUPがあなたに与えるものを正確に与えることができます。 この最後の例でわかるように、標準の’table d’hôte’CUBEとROLLUPを直接表現した’à la carte’グループ化セットと一緒に混合して使用することができます。

なぜ集計で列を結合したいのですか?

いくつかのレポートで2つの列を結合する必要がある場合、2つの列を結合する集計を宣言すると便利です。 最初の例では、ロールアップの年と月を組み合わせて、合計を各テリトリーだけに制限する効果があります。

1
2
3
4
5
6
7
–各地域または年の合計はありません

tを選択します。名前をテリトリーとして、合計(TotalDue)を収益として、
datepart(yyyy、OrderDate)を売上から、datepart(mm、OrderDate)を売上から
。SalesOrderHeader s
内部結合売上高。SalesTerritory T ON S.TerritoryID=T.TerritoryID
Tによるグループ化。,t.name,ROLLUP
((datepart(yyyy,OrderDate),datepart(mm,OrderDate)))

ROLLUP句の余分な括弧は、集計をテリトリーと月/年だけに制限する効果がありました。 それらを除外し、あなたは毎年の合計を取得します。

1
2
3
4
5

となっています。div>6

7
8
9
10
–の合計年以内に各地域の合計
–各領域
— ない合計地域
を選択。 として地域。名前をテリトリーとして、合計(TotalDue)を収益として、
datepart(yyyy、OrderDate)を売上から、datepart(mm、OrderDate)を売上から
。SalesOrderHeader s
内部結合売上高。SalesTerritory T ON S.TerritoryID=T.TerritoryID
Tによるグループ化。,t.nameこれは、特定のデータに対して非常に便利です。

これは、特定のデータに対して非常に便利です。 ここで列を結合する必要はありませんでした。 キューブを作成し、領土の用語が複数の地域の領土を記述するために’Northern’や’Southern’のような言葉を使用した場合、無関係な’northern’領土に適用される奇妙な集計があ 列を組み合わせることで、これを避けることができます。

グループ化セットには、”アラカルト”キューブを行う方法よりも多くのものがありますか?私はこの質問をすることについて恥ずかしがり屋であるかどうかはわかりません。

SQL:1999のグループ化セットは、列の組み合わせを集計し、最大十次元を提供するあらゆる種類の難解なレポートを定義できる豊富な再帰構文を提供します。 集計は入れ子にすることができ、ロールアップ内のキューブを入れ子にしたり、キューブ内のロールアップを入れ子にすることができます。 これについての詳細を調べるために専門家の出版物を読む必要があります。関数Grouping()とGrouping_Id()が提供されているのはなぜですか?列が集計であることを示すためにNULLを使用することは、実際には良い考えではありません。 問題は、グループ化列にnull値が含まれている場合、すべてのnull値が等しいと見なされ、要約を装った単一のNULLグループに配置されることです。 元のデータのNULL値の明らかな難しさを回避するために、Grouping()とGrouping_ID()の2つの関数が提供されています。

Grouping()関数には、ロールアップ、キューブ、またはグループ化セットに参加した列の名前が渡されます。 この行が’all’を意味するNULL値を持つこの列の要約である場合、または値が含まれているかどうかの場合はゼロを返します。

GROUPING_ID関数には、GROUP BYリスト内の式と完全に一致する必要があるリストが渡されます。 GROUPING_IDは、それぞれの集計列のビットマップとして作成されます。 たとえば、territory列にterritoryの名前ではなく’all’territoriesを意味するNULLがあり、それが2番目の列としてリストされている場合、左から2番目のビットが設定されます。 この整数が返されます。通常、行がプライマリまたはセカンダリの集計(0または>0)であるかどうかを示すために使用され、セカンダリの場合は、それ以上の

通常、行がそのディメンションのサマリーである場合に設定されるすべてのディメンション(この例では’Territory’や’Region’など)のビット列をGrouping_ID()値と一緒に含めることをお勧めします。

Grouping_Idが実際に動作する方法を説明するために、ここではgrouping_Idのビットがsummaryのタイプに従って設定される方法を見ていきます。 ビットを表示するには、Phil Factorの関数ToBinaryStringを使用します。

1
2
3
4
5

となっています。div>6

7
8
9
を選択。 として地域。名前をテリトリーとして、合計(TotalDue)を収益として、
datepart(yyyy、OrderDate)を、datepart(mm、OrderDate)を、
右(
dbo。ToBinaryString(–すべてのグループ化された項目をそのままリストします
Grouping_Id(t.,t.name,datepart(yyyy,OrderDate),datepart(mm,OrderDate))
),4)as-リストに4つの列があるので、最後の4文字を使用してください。
販売から。SalesOrderHeader s
内部結合売上高。SalesTerritory T ON S.TerritoryID=T.TerritoryID
キューブによるグループ化(t.,t.これは(もちろんサンプルだけ)…

2303-clip_image006を与えます。png

Related Posts

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です