2016-09-14 15 views
10

mam metody takie jak to:Jak uniknąć PG :: NumericValueOutOfRange podczas korzystania z funkcji SUMA

def self.weighted_average(column) 
    sql = "SUM(#{column} * market_cap)/SUM(market_cap) as weighted_average" 
    Company.select(sql).to_a.first.weighted_average 
    end 

Kiedy kolumna jest decimal, zwraca wartość bez problemu. Ale gdy kolumna jest integer, metoda kończy się błędem PG::NumericValueOutOfRange.

Czy należy zmienić typ kolumny integer na decimal, czy jest jakiś sposób uzyskania wyniku sum bez zmiany typu kolumny?

Odpowiedz

2

Można oddać wartość sprecyzowane być wartość dziesiętną, a więc nie ma potrzeby, aby zmienić typ kolumna:

sql = "SUM(#{column} * CAST(market_cap as decimal(53,8)))/SUM(CAST(market_cap as decimal(53,8))) as weighted_average" 

PS: Zmieniłbym typ kolumny - to jest zgodne następnie.

4

Zawsze można wykonać ze swojej liczby całkowitej.

def self.weighted_average(column) 
    column = column.to_f 
    sql = "SUM(#{column} * market_cap)/SUM(market_cap) as weighted_average" 
    Company.select(sql).to_a.first.weighted_average 
    end 
+0

'column' jest nazwa kolumny modelu. To jest po prostu 'String' lub' Symbol'. – ironsand

2

Sugerowałbym, aby zmienić typ danych do decimal. Ponieważ, gdy SUM pobiera PG::NumericValueOutOfRange, oznacza to, że twój typ danych nie jest wystarczający. Pozwoli to zręcznie obsługiwać ten scenariusz zamiast obejścia.

+0

Wszystkie wartości w kolumnie są wystarczająco małe dla "liczby całkowitej", pojawia się tylko błąd podczas korzystania z funkcji obliczania SQL. Jeśli to możliwe, chcę uniknąć zmiany typu kolumny. – ironsand

2

Postgres documentation napisano o suma() Zwraca typ:

bigint do smallint lub int argumentów liczbowych w BigInt argumentów poza tym taki sam, jak rodzaj argumentach

Oznacza to, że będziesz musiał jakoś zmienić typ danych przekazywany do SUMA. Może to być jedna z następujących wartości:

  • Zmień tabelę, aby zmienić typ danych kolumny.
  • Prześlij kolumnę na inny typ danych w swojej metodzie.
  • Utwórz widok, który rzuci wszystkie liczby całkowite w liczby i użyje tego w swojej metodzie.
2

Próbujesz umieścić wartość dziesiętną w parametrze liczb całkowitych. Chyba użyć wartości ABS(), że nie będzie to możliwe, jeśli nie jesteś w 100% pewien, że wartość% zawsze będzie 0.

Zastosowanie typu float lub funkcja ABS(), jeśli masz mieć INT

0

Yo może próbować odlewania kolumna na dziesiętne

sql = "SUM(CAST(#{column}) AS DECIMAL * market_cap)/SUM(market_cap) as weighted_average" 
Powiązane problemy