SnowConvert: Teradata¶
Operações de dados numéricos¶
Precisão de cálculo¶
O Teradata e o Snowflake tratam os cálculos de forma diferente:
O Teradata arredonda os números após cada etapa de cálculo com base no tipo de dados:
Para tipos decimais, ele mantém a precisão maior
Para os tipos NUMBER, ele mantém a precisão total
O Snowflake armazena todos os números usando o tipo de dados NUMBER, mantendo a precisão total em todos os cálculos. Isso pode levar a resultados diferentes em comparação com o Teradata, especialmente ao trabalhar com tipos decimais, inteiros ou flutuantes.
Essa diferença de comportamento não é ajustada durante a conversão do código, pois normalmente não é o que os desenvolvedores pretendem alterar.
Teradata: SELECT (1.00/28) * 15.00 /* Retorna 0.60 */
O Snowflake arredondará o resultado da divisão (1,00/28) * 15,00 para duas casas decimais: SELECT (1,00/28) * 15,00 = 0,535710 = 0,54
Divisão inteiro-inteiro¶
Ao dividir dois valores inteiros, o Teradata realiza o truncamento (piso), enquanto o Snowflake realiza o arredondamento. Para manter um comportamento consistente durante a migração, a conversão automatizada do código adiciona automaticamente uma instrução TRUNC nesses casos.
Teradata: SELECT (5/3) = 1 /* Retorna 1, pois a divisão inteira arredonda para baixo */
Snowflake: Ao dividir 5 por 3, o resultado é 1,6666666, que é arredondado para 2
Divisão truncada no Snowflake: SELECT TRUNC(5/3) retorna 1
Arredondamento do Banker¶
O Teradata oferece o arredondamento do Banker por meio do parâmetro ROUNDHALFWAYMAGUP, enquanto o Snowflake usa apenas métodos de arredondamento padrão.
SQL |
Teradata |
Snowflake |
---|---|---|
CAST( 1.05 AS DECIMAL(9,1)) |
1.0 |
1.1 |
CAST( 1.15 AS DECIMAL(9,1)) |
1,2 |
1,2 |
CAST( 1.25 AS DECIMAL(9,1)) |
1.2 |
1.3 |
CAST( 1.35 AS DECIMAL(9,1)) |
1.4 |
1.4 |
CAST( 1.45 AS DECIMAL(9,1)) |
1.4 |
1.5 |
CAST( 1.55 AS DECIMAL(9,1)) |
1,6 |
1,6 |
CAST( 1.65 AS DECIMAL(9,1)) |
1.6 |
1.7 |
CAST( 1.75 AS DECIMAL(9,1)) |
1,8 |
1,8 |
CAST( 1.85 AS DECIMAL(9,1)) |
1.8 |
1.9 |
CAST( 1.95 AS DECIMAL(9,1)) |
2,0 |
2,0 |
Conversão de decimal para inteiro¶
O Teradata e o Snowflake tratam os valores decimais de forma diferente. Enquanto o Teradata trunca os valores decimais, o Snowflake os arredonda para o número inteiro mais próximo. Para manter a consistência com o comportamento do Teradata, o processo de conversão adiciona automaticamente uma instrução TRUNC.
SQL |
Teradata |
Snowflake |
---|---|---|
CAST( 1.0 AS INTEGER) |
1 |
1 |
CAST( 1.1 AS INTEGER) |
1 |
1 |
CAST( 1.2 AS INTEGER) |
1 |
1 |
CAST( 1.3 AS INTEGER) |
1 |
1 |
CAST( 1.4 AS INTEGER) |
1 |
1 |
CAST( 1.5 AS INTEGER) |
1 |
2 |
CAST( 1.6 AS INTEGER) |
1 |
2 |
CAST( 1.7 AS INTEGER) |
1 |
2 |
CAST( 1.8 AS INTEGER) |
1 |
2 |
CAST( 1.9 AS INTEGER) |
1 |
2 |
Número sem precisão/escala¶
Quando uma coluna do Teradata NUMBER é definida sem especificar escala ou precisão, ela pode armazenar valores decimais com escala variável (de 0 a 38), desde que a precisão total permaneça dentro de 38 dígitos. No entanto, o Snowflake exige valores fixos de escala e precisão para as colunas NUMBER. Veja um exemplo de como os números são definidos em uma tabela Teradata com esse formato flexível:
CREATE MULTISET TABLE DATABASEXYZ.TABLE_NUMS
(NUM_COL1 NUMBER(*),
NUM_COL2 NUMBER,
NUM_COL3 NUMBER(38,*));
A tabela a seguir mostra dois exemplos de valores que excedem os limites de tamanho de coluna do Snowflake. Esses valores podem aparecer em qualquer uma das colunas do Teradata mostradas anteriormente.
Valor 1: 123.345.678.901.234.567.891.012.0123456789
Valor 2: 123.12345678901234567890
Esses valores numéricos exigiriam um tipo de dados NUMBER(42, 20), que excede o limite máximo de precisão de 38 do Snowflake. A Snowflake está trabalhando atualmente na implementação da funcionalidade de precisão e escala flexíveis.
Truncamento em INSERT para instruções SQL DML¶
O Teradata trunca automaticamente os valores de cadeia de caracteres que excedem o comprimento de campo definido durante a inserção. Embora o SnowConvert mantenha os mesmos comprimentos de campo durante a conversão (por exemplo, VARCHAR(20) continua sendo VARCHAR(20)), o Snowflake não trunca automaticamente as cadeias de caracteres grandes demais. Se o seu processo de ingestão de dados depender do truncamento automático, você precisará modificá-lo manualmente adicionando uma função LEFT(). O SnowConvert intencionalmente não adiciona o truncamento automaticamente devido ao possível impacto em toda a base de código.
Exemplo de problema de padrão de ponto flutuante:¶
/* <sc-table> TABLE DUMMY.EXAMPLE </sc-table> */
/**** WARNING: SET TABLE FUNCTIONALITY NOT SUPPORTED ****/
CREATE TABLE DUMMY.PUBLIC.EXAMPLE (
LOGTYPE INTEGER,
OPERSEQ INTEGER DEFAULT 0,
RUNTIME FLOAT /**** ERROR: DEFAULT CURRENT_TIME NOT VALID FOR DATA TYPE ****/
);
Agregação de dados de ponto flutuante¶
Os números de ponto flutuante são representações aproximadas dos valores decimais. Devido a essas aproximações, diferentes sistemas de banco de dados podem produzir resultados ligeiramente diferentes ao realizar cálculos e agregações com tipos de dados flutuantes. Essa variação ocorre porque cada sistema de banco de dados lida com a aritmética de ponto flutuante e com o arredondamento à sua própria maneira.
Outras considerações¶
Eliminação de junções¶
O Snowflake executa as consultas do SQL exatamente como foram escritas, incluindo todas as uniões especificadas, independentemente de elas afetarem os resultados finais. Ao contrário do Snowflake, o Teradata pode remover automaticamente as junções desnecessárias usando relacionamentos de chave primária e estrangeira definidos na estrutura da tabela. Esse recurso do Teradata ajuda principalmente a evitar consultas mal escritas e, normalmente, só é uma preocupação quando o código foi escrito especificamente para usar esse recurso. Se o seu código existente foi projetado para aproveitar o recurso de eliminação de junções do Teradata, as ferramentas de conversão de código automatizadas não poderão resolver essa limitação. Nesses casos, talvez você precise redesenhar partes da sua solução.
Usando funções Window com max() e order by
Comportamento e padrões do Teradata:¶
Padrão: Quando uma cláusula ORDER BY está presente, mas nenhuma cláusula ROWS ou ROWS BETWEEN é especificada, as funções de agregação de janela do Teradata SQL usam automaticamente ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.
Comportamento e padrões do Snowflake:¶
Padrão: Quando você usa uma função de agregação de janela com uma cláusula ORDER BY, mas sem especificar ROWS ou ROWS BETWEEN, o Snowflake aplica automaticamente ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW como o quadro da janela.
Exemplo:
Abaixo está uma tabela de amostra chamada TEST_WIN que mostra os dados salariais dos funcionários em vários departamentos.
DEPT_NM | DEPT_NO | EMP_NO | SALARY |
---|---|---|---|
SALES | 10 | 11 | 5000 |
SALES | 10 | 12 | 6000 |
HR | 20 | 21 | 1000 |
HR | 20 | 22 | 2000 |
PS | 30 | 31 | 7000 |
PS | 30 | 32 | 9000 |
O código a seguir, quando executado no Teradata, calcula o salário mais alto entre todos os funcionários, agrupados por departamento.
SELECT DEPT_NM, SALARY ,DEPT_NO,
MAX(SALARY) OVER ( ORDER BY DEPT_NO ) AS MAX_DEPT_SALARY
FROM TEST_WIN;
DEPT_NM | SALARY | DEPT_NO | MAX_DEPT_SALARY |
---|---|---|---|
SALES | 6000 | 10 | 9000 |
SALES | 5000 | 10 | 9000 |
HR | 2000 | 20 | 9000 |
HR | 1000 | 20 | 9000 |
PS | 7000 | 30 | 9000 |
PS | 9000 | 30 | 9000 |
Ao executar o código convertido usando Snowflake-SnowConvert, você poderá observar resultados diferentes (valores destacados). Essas diferenças são esperadas e estão alinhadas com as configurações padrão do Snowflake.
SELECT DEPT_NM, SALARY ,DEPT_NO,
MAX(SALARY) OVER ( ORDER BY DEPT_NO ) AS MAX_DEPT_SALARY
FROM TEST_WIN;
DEPT_NM | SALARY | DEPT_NO | MAX_DEPT_SALARY |
---|---|---|---|
SALES | 5000 | 10 | 6000 |
SALES | 6000 | 10 | 6000 |
HR | 1000 | 20 | 6000 |
HR | 2000 | 20 | 6000 |
PS | 7000 | 30 | 9000 |
PS | 9000 | 30 | 9000 |
Para obter resultados idênticos aos do Teradata, você deve especificar o valor ROWS/RANGE conforme mostrado no código abaixo.
SELECT DEPT_NM, SALARY ,DEPT_NO,
MAX(SALARY) OVER ( ORDER BY DEPT_NO RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS MAX_DEPT_SALARY
FROM TEST WIN;
DEPT_NM | SALARY | DEPT_NO | MAX_DEPT_SALARY |
---|---|---|---|
SALES | 5000 | 10 | 9000 |
SALES | 6000 | 10 | 9000 |
HR | 1000 | 20 | 9000 |
HR | 2000 | 20 | 9000 |
PS | 7000 | 30 | 9000 |
PS | 9000 | 30 | 9000 |
A cláusula RANGE/ROWS define explicitamente como as linhas são ordenadas. Você pode obter resultados semelhantes removendo completamente a cláusula ORDER BY.
Referências¶
Snowflake: https://docs.snowflake.com/en/sql-reference/functions-analytic.html Teradata: https://docs.teradata.com/r/756LNiPSFdY~4JcCCcR5Cw/dIV_fAtkK3UeUIQ5_uucQw