2016-06-22 38 views
18

Frage ist ziemlich im Titel. Ich kann keine detaillierte Dokumentation zu den Unterschieden finden.Was ist der Unterschied zwischen den Operatoren cube, rollup und groupBy?

Ich bemerke einen Unterschied, weil ich beim Austausch von Cube und groupBy Funktionsaufrufen unterschiedliche Ergebnisse bekomme. Mir ist aufgefallen, dass ich für das Ergebnis, das 'cube' verwendet, viele Null-Werte für die Ausdrücke erhalten habe, nach denen ich oft gruppiert bin.

Antwort

38

Diese sind nicht für die gleiche Funktionsweise vorgesehen. groupBy ist einfach ein Äquivalent der GROUP BY-Klausel in Standard-SQL. Mit anderen Worten

table.groupBy($"foo", $"bar") 

entspricht:

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

cube zu CUBE Erweiterung GROUP BY entspricht. Es nimmt eine Liste von Spalten und wendet Aggregatausdrücke auf alle möglichen Kombinationen der Gruppierungsspalten an. Können sagen, Sie Daten wie dieses:

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| 
// +---+---+ 

und Sie berechnen cube(x, y) mit Zählung als eine Aggregation:

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 
// +----+----+-----+ 

Eine ähnliche Funktion cube ist rollup, die von links nach rechts hierarchische Teilsummen berechnet :

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 
// +----+----+-----+ 

Ju st zum Vergleich lässt das Ergebnis der Ebene groupBy sehen:

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 
// +---+---+-----+ 

Fassen wir zusammen:

  • Wenn Ebene GROUP BY mit jeder Zeile enthalten nur einmal in seiner entsprechenden Zusammenfassung.
  • Mit GROUP BY CUBE(..) ist jede Zeile in der Zusammenfassung jeder Kombination von Ebenen enthalten, die es darstellt, Wildcards enthalten. Logischerweise ist die obige gleichwertig wie diese etwas gezeigt (vorausgesetzt, wir NULL Platzhalter verwenden könnten):

    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 
    
  • Mit GROUP BY ROLLUP(...) ist ähnlich CUBE aber funktioniert hierarchisch von colums von links nach rechts zu füllen.

    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 und CUBE von Data-Warehousing-Erweiterungen kommen also, wenn Sie ein besseres Verständnis zu bekommen, wie das funktioniert auch Dokumentation Ihrer Lieblings RDMBS überprüfen. Zum Beispiel PostgreSQL eingeführt sowohl in 9.5 und these are relatively well documented.