本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
數值的計算
在本文中,計算是指二進位數學運算:加、減、乘和除。本節說明這些操作的預期傳回類型,以及用於在涉及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結果時擴展。在這個表格中,p1
和 s1
代表計算式中第一個運算元的精確度和小數位數,p2
和 s2
代表第二個運算元的精確度和小數位數。(無論這些計算如何,結果的最高精確度為 38、結果的最大小數位數為 38。)
作業 | 結果的精確度與小數位數 |
---|---|
+ 或 - | 擴展 = max(s1,s2) 精確度 = |
* | 擴展 = s1+s2 精確度 = |
/ | 擴展 = max(4,s1+p2-s2+1) 精確度 = |
例如,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)