數值的計算 - Amazon Redshift

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

數值的計算

在本文中,計算是指二進位數學運算:加、減、乘和除。本節說明這些操作的預期傳回類型,以及用於在涉及DECIMAL資料類型時判斷精確度和規模的特定公式。

在查詢處理作業期間計算數值時,可能會遇到無法進行計算的情況,而且查詢會傳回數值溢位錯誤。您也可能會遇到計算值的小數位數改變或出乎意料的情況。針對某些運算,您可以使用明確轉換 (類型提升) 或 Amazon Redshift 設定參數,來解決這些問題。

如需使用 SQL函數進行類似運算的結果資訊,請參閱 彙總函數

計算的傳回類型

根據 Amazon Redshift 中所支援的一組數值資料類型,下表顯示了加法、減法、乘法和除法運算預期的傳回類型。表格左側的第一欄代表計算中的第一個運算元,最上面的列代表第二個運算元。

運算元 1 運算元 2 傳回類型
INT2 INT2 INT2
INT2 INT4 INT4
INT2 INT8 INT8
INT2 DECIMAL DECIMAL
INT2 FLOAT4 FLOAT8
INT2 FLOAT8 FLOAT8
INT4 INT4 INT4
INT4 INT8 INT8
INT4 DECIMAL DECIMAL
INT4 FLOAT4 FLOAT8
INT4 FLOAT8 FLOAT8
INT8 INT8 INT8
INT8 DECIMAL DECIMAL
INT8 FLOAT4 FLOAT8
INT8 FLOAT8 FLOAT8
DECIMAL DECIMAL DECIMAL
DECIMAL FLOAT4 FLOAT8
DECIMAL FLOAT8 FLOAT8
FLOAT4 FLOAT8 FLOAT8
FLOAT8 FLOAT8 FLOAT8

計算DECIMAL結果的精確度和規模

下表摘要說明計算所得精確度的規則,並在數學運算傳回DECIMAL結果時擴展。在這個表格中,p1s1 代表計算式中第一個運算元的精確度和小數位數,p2s2 代表第二個運算元的精確度和小數位數。(無論這些計算如何,結果的最高精確度為 38、結果的最大小數位數為 38。)

作業 結果的精確度與小數位數
+ 或 - 擴展 = max(s1,s2)

精確度 = max(p1-s1,p2-s2)+1+scale

* 擴展 = s1+s2

精確度 = p1+p2+1

/ 擴展 = max(4,s1+p2-s2+1)

精確度 = p1-s1+ s2+scale

例如,SALES資料表中的 PRICEPAID和 COMMISSION資料欄都是 DECIMAL(8,2) 資料欄。如果您PRICEPAID除以 COMMISSION(反之亦然),則會套用公式,如下所示:

Precision = 8-2 + 2 + max(4,2+8-2+1) = 6 + 2 + 9 = 17 Scale = max(4,2+8-2+1) = 9 Result = DECIMAL(17,9)

下列計算是計算對 UNION、 和 等設定運算子EXCEPT或 INTERSECT和 等函數對DECIMAL值執行之操作所產生的精確度COALESCE和規模的一般規則DECODE:

Scale = max(s1,s2) Precision = min(max(p1-s1,p2-s2)+scale,19)

例如,具有一 DECIMAL(7,2) 欄的DEC1資料表會與具有一 DECIMAL(15,3) 欄的DEC2資料表聯結,以建立DEC3資料表。的結構描述DEC3顯示資料欄變成 NUMERIC(15,3) 資料欄。

create table dec3 as select * from dec1 union select * from dec2;

結果

select "column", type, encoding, distkey, sortkey from pg_table_def where tablename = 'dec3'; column | type | encoding | distkey | sortkey -------+---------------+----------+---------+--------- c1 | numeric(15,3) | none | f | 0

在上述的範例中,會如下套用公式:

Precision = min(max(7-2,15-3) + max(2,3), 19) = 12 + 3 = 15 Scale = max(2,3) = 3 Result = DECIMAL(15,3)

關於除法運算的備註

對於部門操作, divide-by-zero條件會傳回錯誤。

在計算出精確度和小數位數之後,會套用 100 個小數位數的限制。如果計算結果的小數位數大於 100,除的結果會如下設定小數位數:

  • 精確度 = precision - (scale - max_scale)

  • 擴展 = max_scale

如果計算出的精確度大於最高精確度 (38),則精確度會降低為 38,而小數位數會變成下列算式的結果:max((38 + scale - precision), min(4, 100))

溢位狀況

會針對所有數值運算檢查溢位。DECIMAL 精確度為 19 或以下的 資料會儲存為 64 位元整數。DECIMAL 精確度大於 19 的資料會儲存為 128 位元整數。所有DECIMAL值的最大精確度為 38,最大規模為 37。當數值超出這些限值時,會出現溢位錯誤,這會同時發生於中間的和最終的結果集:

  • 當特定資料值不符合轉換函式所要求的精確度或指定的小數位數時,明確轉換作業會產生執行時期的溢位錯誤。例如,您無法從SALES資料表 (DECIMAL8,2) 欄) 中的PRICEPAID資料欄轉換所有值,並傳回 DECIMAL(7,3) 結果:

    select pricepaid::decimal(7,3) from sales; ERROR: Numeric data overflow (result precision)

    發生此錯誤是因為無法轉換資料PRICEPAID欄中某些較大的值。

  • 在乘法運算所產生的結果中,其小數位數是每個運算元小數位數的總和。例如,如果兩個運算元都有 4 個小數位數,結果的小數位數是 8 個,使得小數點的左邊只有 10 個位數。因此,在將兩個都擁有大量小數位數的大數值相乘時,就會相當容易產生溢位狀況。

    下列範例會導致溢位錯誤。

    SELECT CAST(1 AS DECIMAL(38, 20)) * CAST(10 AS DECIMAL(38, 20)); ERROR: 128 bit numeric data overflow (multiplication)

    您可以使用除法而不是乘法來解決溢位錯誤。使用以下範例除以 1 除以原始除數。

    SELECT CAST(1 AS DECIMAL(38, 20)) / (1 / CAST(10 AS DECIMAL(38, 20))); +----------+ | ?column? | +----------+ | 10 | +----------+

使用 INTEGER和 DECIMAL類型的數值計算

當計算中的其中一個運算元具有INTEGER資料類型,而另一個運算元為 時DECIMAL,INTEGER運算元會隱含轉換為 DECIMAL:

  • INT2 (SMALLINT) 轉換為 DECIMAL(5,0)

  • INT4 (INTEGER) 轉換為 DECIMAL(10,0)

  • INT8 (BIGINT) 轉換為 DECIMAL(19,0)

例如,如果您將 SALES.COMMISSION、DECIMAL(8,2) 欄和 SALES. QTYSOLDSMALLINT欄相乘,則此計算會轉換為:

DECIMAL(8,2) * DECIMAL(5,0)