

 Amazon Redshift 將不再支援從修補程式 198 開始建立新的 Python UDFs。現有 Python UDF 將繼續正常運作至 2026 年 6 月 30 日。如需詳細資訊，請參閱[部落格文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

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

# 數值的計算
<a name="r_numeric_computations201"></a>

在本文中，*計算*是指二進位數學運算：加、減、乘和除。本節說明這些運算預期的傳回類型，以及使用 DECIMAL 資料類型時，用來決定精確度與小數位數的特定公式。

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

關於使用 SQL 函式進行類似計算的結果，詳細資訊請參閱 [彙總函數](c_Aggregate_Functions.md)。

## 計算的傳回類型
<a name="r_numeric_computations201-return-types-for-computations"></a>

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

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/redshift/latest/dg/r_numeric_computations201.html)

## 計算出 DECIMAL 結果的精確度和小數位數
<a name="r_numeric_computations201-precision-and-scale-of-computed-decimal-results"></a>

下表顯示摘要，說明在數學運算傳回 DECIMAL 結果時，用來計算結果精確度和小數位數的規則。在這個表格中，`p1` 和 `s1` 代表計算式中第一個運算元的精確度和小數位數，`p2` 和 `s2` 代表第二個運算元的精確度和小數位數。(無論這些計算如何，結果的最高精確度為 38、結果的最大小數位數為 38。) 

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/redshift/latest/dg/r_numeric_computations201.html)

例如，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)
```

下列的計算是一般規則，適用於針對 DECIMAL 數值的運算 (使用 UNION、INTERSECT 和 EXCEPT 等集合運算子，或 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)
```

## 關於除法運算的備註
<a name="r_numeric_computations201-notes-on-division-operations"></a>

如果是除法運算，除以 0 的情況會傳回錯誤。

在計算出精確度和小數位數之後，會套用 100 個小數位數的限制。如果計算結果的小數位數大於 100，除的結果會如下設定小數位數：
+ 精確度 = ` precision - (scale - max_scale)` 
+ 擴展 = ` max_scale ` 

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

## 溢位狀況
<a name="r_numeric_computations201-overflow-conditions"></a>

會針對所有數值運算檢查溢位。具有 19 個 (含) 以下有效位數 (精確度) 的 DECIMAL 資料，會儲存為 64 位元整數。具有 19 個 (含) 以上有效位數 (精確度) 的 DECIMAL 資料，會儲存為 128 位元整數。所有 DECIMAL 數值的最高精確度為 38、最大小數位數為 37。當數值超出這些限值時，會出現溢位錯誤，這會同時發生於中間的和最終的結果集：
+ 當特定資料值不符合轉換函式所要求的精確度或指定的小數位數時，明確轉換作業會產生執行時期的溢位錯誤。例如，您無法從 SALES 資料表中的 PRICEPAID 資料欄 (DECIMAL(8,2) 資料欄) 轉換所有的數值，然後傳回 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 類型的數值計算
<a name="r_numeric_computations201-numeric-calculations-with-integer-and-decimal-types"></a>

當計算式中的其中一個運算元具有 INTEGER 資料類型，而另一個運算元為 DECIMAL，INTEGER 運算元會隱含轉換為 DECIMAL：
+ INT2 (SMALLINT) 會轉換為 DECIMAL(5,0) 
+ INT4 (INTEGER) 會轉換為 DECIMAL(10,0) 
+ INT8 (BIGINT) 會轉換為 DECIMAL(19,0) 

例如，如果將 DECIMAL(8,2) 資料欄 SALES.COMMISSION 乘以 SMALLINT 資料欄 SALES.QTYSOLD，此計算式會進行如下的轉換：

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