2016-12-05 2 views
0

Mit einer Hive-Tabelle wie unten möchte ich einen gewichteten gleitenden Durchschnitt berechnen. In Tabelle 1 ist ein Beispiel für einen solchen gewichteten gleitenden Durchschnitt angegeben. Der Wert jeder Spalte istgewichteter gleitender Durchschnitt mit Hive SQL

col_value = (1 * n) + (0.75 * n-1) + (0.5 * n-2) + (0.25 * n-3) 
where n is the value at the current row, n-1 the value at the above row, etc. 

Weitere Informationen über gewichtete gleitende Durchschnitte auf dem corresponding Wikipedia section

Im stecken nach wie so den gleitenden Durchschnitt Berechnung:

Codebeispiel 1: Abfrage bisher

Tabelle 1:

id value weighted_moving_average code_sample_1 
... 
11  0  0      0 
12  1  1      0.25 
13  0  0.75      0.25 
14  0  0.5      0.25 
15  0  0.25      0.25 
16  0  0      0 
... 
+1

Können Sie die Logik für 'gewollte' Spalte erklären? –

+0

Was bekommen Sie von der Abfrage? –

+0

Vielen Dank für Anregungen, siehe aktualisierte Frage –

Antwort

1

Wenn Sie möchten, dass die Fenstergröße leicht geändert werden kann, dann wäre die Implementierung wesentlich anders.

(Bitte beachten Sie, dass ich das in entwickelt, weil ich nicht bewusst bin von jeder Website, die ich SQL testen kann. Sie müssen möglicherweise einige Syntax zwicken.)

Declare @thisManyRows int = 3; 
With rowNumber_cte As (
    Select 
     id, 
     [Value], 
     RowNo = Row_Number() Over (Order By id) 
     From Table1), 
windows_cte As (
    Select 
     b_id = b.id, 
     j_id = j.id, 
     j.[Value], 
     RowNo2 = @thisManyRows + 1 - Row_Number() Over (Partition By b.id Order By j.id desc), 
     n = Count(j.[Value]) Over (Partition By b.id) 
     From rowNumber_cte As b 
     Join rowNumber_cte As j On j.RowNo Between b.RowNo - @thisManyRows + 1 And b.RowNo) 
Select 
    id = b_id, 
    [Value] = Sum(Case When b_id = j_id Then [Value] Else Null End), 
    WeightedAverage = Sum([Value] * 1.0 * (RowNo2 *1.0/@thisManyRows))/Min(n) 
    From windows_cte 
    Group By b_id; 

Ich werde, was zu erklären, Dies geschieht, weil es ein bisschen kryptisch ist:

  1. Setzen Sie die Variable auf die Anzahl der Zeilen, die für den gleitenden Durchschnitt berücksichtigt werden sollen (einschließlich der aktuellen Zeile).
  2. In der rowNumber_cte vergeben wir eine Zeilennummer, wir tun dies, weil wir nicht davon ausgehen, dass id wird sequenziell sein.
  3. Im windows_cte wir die rowNumber_cte auf sich selbst verbinden, so dass jede Zeile auf alle Zeilen verbunden ist, dass es Fenster der Berechnung bilden (mit Bezug auf die @thisManyRows Variable. Diese CTE führt auch ein neues RowNo2 Feld, das im Grunde endet der Zähler der Bruchzahl, für die der Wert dieser Zeile zum gewichteten gleitenden Durchschnitt beiträgt (dh die aktuelle Zeile hat RowNo2 = 4 und ein 4/4-Gewicht)
  4. windows_cte berechnet auch die Anzahl von Zeilen in dem Fenster, um Zeilen am Anfang der Daten, die kein volles Fenster haben, besser zu behandeln
  5. Die endgültigen Auswahlgruppen von id multipliziert die [Value] jeder Zeile im Fenster mit seinem Gewicht und teilt sie dann durch die Anzahl der Zeilen im Fenster: n.
0

Das ist nicht schick, aber es ist ein Anfang.

SELECT 
    *, 
    (SUM (value*0.25) OVER (ORDER BY id ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) + 
    SUM (value*0.25) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) + 
    SUM (value*0.25) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) + 
    value * 0.25)/
    COUNT (value) OVER (ORDER BY id ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) 
FROM 
    table; 
+0

Gibt es eine Möglichkeit, die Fenstergröße dynamisch zu gestalten? –

+0

Nicht in seiner Methode. Ich kann mir eine andere Methode vorstellen, die dynamisch sein könnte, aber ich habe keine Zeit, sie jetzt zu schreiben. – mendosi

Verwandte Themen