La question est à peu près dans le titre. Je ne trouve aucune documentation détaillée concernant les différences.
Je remarque une différence car lorsque j'échange des appels de fonction cube et groupBy, j'obtiens des résultats différents. J'ai remarqué que pour le résultat en utilisant "cube", j'ai obtenu beaucoup de valeurs nulles sur les expressions que je regroupais souvent.
Ceux-ci ne sont pas destinés à fonctionner de la même manière. groupBy
est simplement un équivalent de la clause GROUP BY
en SQL standard. En d'autres termes
table.groupBy($"foo", $"bar")
est équivalent à:
SELECT foo, bar, [agg-expressions] FROM table GROUP BY foo, bar
cube
est équivalent à CUBE
extension à GROUP BY
. Il prend une liste de colonnes et applique des expressions agrégées à toutes les combinaisons possibles des colonnes de regroupement. Disons que vous avez des données comme celle-ci:
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|
// +---+---+
et vous calculez cube(x, y)
avec count comme agrégation:
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
// +----+----+-----+
Une fonction similaire à cube
est rollup
qui calcule les sous-totaux hiérarchiques de gauche à droite:
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
// +----+----+-----+
Juste à titre de comparaison, voyons le résultat de plain 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
// +---+---+-----+
Résumer:
GROUP BY
Simple, chaque ligne n'est incluse qu'une seule fois dans son résumé correspondant.Avec GROUP BY CUBE(..)
chaque ligne est incluse dans le résumé de chaque combinaison de niveaux qu'elle représente, caractères génériques inclus. Logiquement, l'illustration ci-dessus équivaut à quelque chose comme ça (en supposant que nous pourrions utiliser les espaces réservés 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
Avec GROUP BY ROLLUP(...)
est similaire à CUBE
mais fonctionne hiérarchiquement en remplissant les colonnes de gauche à droite.
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
ROLLUP
et CUBE
proviennent d'extensions d'entreposage de données, donc si vous voulez mieux comprendre comment cela fonctionne, vous pouvez également consulter la documentation de votre RDMBS préféré. Par exemple, PostgreSQL a été introduit à la fois en 9.5 et ceux-ci sont relativement bien documentés .