Computações com valores numéricos
Neste contexto, computação refere-se à operações matemáticas binárias: adição, subtração, multiplicação e divisão. Esta seção descreve os tipos de retorno previstos para essas operações, assim como a fórmula específica que é aplicada para determinar a precisão e escala quando dados do tipo DECIMAL estão envolvidos.
Quando os valores numéricos são computados durante o processamento da consulta, você pode encontrar casos onde o cálculo é impossível e a consulta retorna um erro de transbordamento numérico. Você também pode encontrar casos em que a escala de valores computados varia ou é inesperada. Para algumas operações, você pode usar conversão explícita (promoção de tipo) ou parâmetros de configuração do Amazon Redshift para solucionar esses problemas.
Para obter informações sobre os resultados de computações semelhantes com funções SQL, consulte Funções agregadas.
Tipos de retorno para computações
Dado o conjunto de tipos de dados numéricos suportados no Amazon Redshift, a tabela a seguir mostra os tipos de retorno esperados para operações de adição, subtração, multiplicação e divisão. A primeira coluna do lado esquerdo da tabela representa o primeiro operando no cálculo e a linha superior representa o segundo operando.
Operando 1 | Operando 2 | Tipo de retorno |
---|---|---|
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 |
Precisão e escala de resultados de DECIMAL computados
A tabela a seguir resume as regras para precisão e escala resultantes de computação quando operações matemáticas retornam resultados DECIMAIS. Nessa tabela, p1
e s1
representam a precisão e escala do primeiro operando no cálculo e p2
e s2
representam a precisão e escala de segundo operando. (Independentemente desses cálculos, a precisão máxima de resultado é 38 e a escala máxima de resultado é 38.)
Operation | Precisão e escala de resultados |
---|---|
+ ou - | Dimensionar = max(s1,s2) Precisão = |
* | Dimensionar = s1+s2 Precisão = |
/ | Dimensionar = max(4,s1+p2-s2+1) Precisão = |
Por exemplo, as colunas PRICEPAID e COMMISSION na tabela SALES são ambas colunas do tipo DECIMAL(8,2). Se você dividir PRICEPAID pela COMMISSION (ou vice-versa), a fórmula será aplicada da seguinte forma:
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)
O seguinte cálculo é a regra geral para computação da precisão e escala resultantes para operações executadas em valores DECIMAIS com operadores de conjunto tais como UNION, INTERSECT e EXCEPT ou funções como COALESCE e DECODE:
Scale = max(s1,s2) Precision = min(max(p1-s1,p2-s2)+scale,19)
Por exemplo, uma tabela DEC1 com uma colina DECIMAL(7,2) é unida a uma tabela DEC2 com uma coluna DECIMAL(15,3) para criar uma tabela DEC3. O esquema de DEC3 mostra que a coluna se torna uma coluna NUMERIC(15,3).
create table dec3 as select * from dec1 union select * from dec2;
Resultado
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
No exemplo acima, a fórmula é aplicada da seguinte forma:
Precision = min(max(7-2,15-3) + max(2,3), 19) = 12 + 3 = 15 Scale = max(2,3) = 3 Result = DECIMAL(15,3)
Observações sobre operações de divisão
Para operações de divisão, condições de dividir por zero retornam erros.
O limite de escala de 100 é aplicado após o cálculo da precisão e escala. Se a escala de resultados calculada for maior que 100, os resultados da divisão serão escalados da seguinte forma:
-
Precisão =
precision - (scale - max_scale)
-
Dimensionar =
max_scale
Se a precisão calculada for maior do que a precisão máxima (38), a precisão será reduzida para 38 e a escala será o resultado de: max((38 + scale - precision), min(4, 100))
Condições de transbordamento
O transbordamento é verificado para todas as computações numéricas. Dados DECIMAIS com uma precisão de 19 ou o menos são armazenados como números inteiros de 64 bits. Dados DECIMAIS com uma precisão maior que 19 são armazenados como números inteiros de 128 bits. A precisão máxima para todos os valores DECIMAIS é 38 e a escala máxima é 37. Erros de transbordamento ocorrem quando um valor excede esses limites, que se aplicam a conjuntos de resultados intermediário e final:
-
A conversão explícita resulta em erros de transbordamento de tempo de execução quando valores de dados específicos não se enquadram na precisão ou escala necessárias especificadas pela função de conversão. Por exemplo, você não pode converter todos os valores da coluna PRICEPAID na tabela SALES (uma coluna DECIMAL(8,2)) e retornar um resultado DECIMAL(7,3):
select pricepaid::decimal(7,3) from sales;
ERROR: Numeric data overflow (result precision)
Este erro ocorre porque alguns dos valores maiores na coluna PRICEPAID não podem ser convertidos.
-
As operações de multiplicação produzem resultados em que a escala de resultados é a soma de escala de cada operando. Se ambos os operandos têm uma escala de 4, por exemplo, a escala de resultados é 8, deixando apenas 10 dígitos para o lado esquerdo do ponto decimal. Portanto, é relativamente fácil se deparar com condições de transbordamento ao multiplicar dois números grandes que possuem uma escala significativa.
O exemplo a seguir retorna um erro de transbordamento.
SELECT CAST(1 AS DECIMAL(38, 20)) * CAST(10 AS DECIMAL(38, 20));
ERROR: 128 bit numeric data overflow (multiplication)
Você pode contornar o erro de transbordamento usando divisão em vez de multiplicação. Use o exemplo a seguir para dividir por 1 dividido pelo divisor original.
SELECT CAST(1 AS DECIMAL(38, 20)) / (1 / CAST(10 AS DECIMAL(38, 20)));
+----------+ | ?column? | +----------+ | 10 | +----------+
Cálculos numéricos com os tipos INTEGER e DECIMAL
Quando um dos operandos em um cálculo tem um tipo de dado INTEGER e o outro operando é DECIMAL, o operando INTEGER é implicitamente convertido como um DECIMAL:
-
INT2 (SMALLINT) é convertido como DECIMAL(5,0)
-
INT4 (INTEGER) é convertido como DECIMAL(10,0)
-
INT8 (BIGINT) é convertido como DECIMAL(19,0)
Por exemplo, se você multiplicar SALES.COMMISSION, uma coluna DECIMAL(8,2), e SALES.QTYSOLD, uma coluna SMALLINT, este cálculo será convertido como:
DECIMAL(8,2) * DECIMAL(5,0)