web-dev-qa-db-ja.com

キューブ、ロールアップ、およびgroupBy演算子の違いは何ですか?

質問はほとんどタイトルにあります。違いに関する詳細なドキュメントが見つかりません。

キューブとgroupBy関数呼び出しを交換すると、結果が異なるため、違いに気付きました。 「キューブ」を使用した結果では、頻繁にグループ化する式で多くのヌル値を取得しました。

31
Eric Staner

これらは同じ方法で動作することを意図していません。 groupByは、単に標準SQLの_GROUP BY_句と同等です。言い換えると

_table.groupBy($"foo", $"bar")
_

以下と同等です:

_SELECT foo, bar, [agg-expressions] FROM table GROUP BY foo, bar
_

cubeは_GROUP BY_のCUBE拡張と同等です。列のリストを受け取り、集約式をグループ化列のすべての可能な組み合わせに適用します。次のようなデータがあるとしましょう:

_val df = Seq(("foo", 1L), ("foo", 2L), ("bar", 2L), ("bar", 2L)).toDF("x", "y")
_
_df.show

// +---+---+
// |  x|  y|
// +---+---+
// |foo|  1|
// |foo|  2|
// |bar|  2|
// |bar|  2|
// +---+---+
_

そして、カウントとしてcube(x, y)を集計として計算します:

_df.cube($"x", $"y").count.show

// +----+----+-----+     
// |   x|   y|count|
// +----+----+-----+
// |null|   1|    1|   <- count of records where y = 1
// |null|   2|    3|   <- count of records where y = 2
// | foo|null|    2|   <- count of records where x = foo
// | bar|   2|    2|   <- count of records where x = bar AND y = 2
// | foo|   1|    1|   <- count of records where x = foo AND y = 1
// | foo|   2|    1|   <- count of records where x = foo AND y = 2
// |null|null|    4|   <- total count of records
// | bar|null|    2|   <- count of records where x = bar
// +----+----+-----+
_

cubeと同様の関数は、左から右へ階層小計を計算するrollupです。

_df.rollup($"x", $"y").count.show
// +----+----+-----+
// |   x|   y|count|
// +----+----+-----+
// | foo|null|    2|   <- count where x is fixed to foo
// | bar|   2|    2|   <- count where x is fixed to bar and y is fixed to  2
// | foo|   1|    1|   ...
// | foo|   2|    1|   ...
// |null|null|    4|   <- count where no column is fixed
// | bar|null|    2|   <- count where x is fixed to bar
// +----+----+-----+
_

比較のために、単純なgroupByの結果を見てみましょう:

_df.groupBy($"x", $"y").count.show

// +---+---+-----+
// |  x|  y|count|
// +---+---+-----+
// |foo|  1|    1|   <- this is identical to x = foo AND y = 1 in CUBE or ROLLUP
// |foo|  2|    1|   <- this is identical to x = foo AND y = 2 in CUBE or ROLLUP
// |bar|  2|    2|   <- this is identical to x = bar AND y = 2 in CUBE or ROLLUP
// +---+---+-----+
_

要約する:

  • プレーン_GROUP BY_を使用すると、すべての行が対応するサマリーに1回だけ含まれます。
  • GROUP BY CUBE(..)を使用すると、すべての行がそれが表すレベルの各組み合わせの要約に含まれ、ワイルドカードが含まれます。論理的には、上記の例は次のようなものに相当します(NULLプレースホルダーを使用できると仮定):

    _SELECT NULL, NULL, COUNT(*) FROM table
    UNION ALL
    SELECT x,    NULL, COUNT(*) FROM table GROUP BY x
    UNION ALL
    SELECT NULL, y,    COUNT(*) FROM table GROUP BY y
    UNION ALL
    SELECT x,    y,    COUNT(*) FROM table GROUP BY x, y
    _
  • GROUP BY ROLLUP(...)CUBEと似ていますが、列を左から右に埋めることで階層的に機能します。

    _SELECT NULL, NULL, COUNT(*) FROM table
    UNION ALL
    SELECT x,    NULL, COUNT(*) FROM table GROUP BY x
    UNION ALL
    SELECT x,    y,    COUNT(*) FROM table GROUP BY x, y
    _

ROLLUPCUBEは、データウェアハウジング拡張機能に由来するため、これがどのように機能するかをより深く理解したい場合は、お気に入りのRDMBSのドキュメントを確認することもできます。例えば、PostgreSQLは9.5と これらは比較的よく文書化されています の両方で導入されました。

63
zero323