SnowConvert : Teradata¶
Opérations sur les données numériques¶
Précision des calculs¶
Teradata et Snowflake traitent les calculs différemment :
Teradata arrondit les données après chaque étape de calcul en fonction du type de données :
Pour les types décimaux, il conserve la plus grande précision
Pour les types NUMBER, il conserve toute sa précision
Snowflake stocke toutes les données en utilisant le type de données NUMBER, ce qui permet de maintenir une précision totale tout au long des calculs. Cela peut conduire à des résultats différents de ceux de Teradata, en particulier lorsque vous travaillez avec des types décimaux, entiers ou flottants.
Cette différence de comportement n’est pas corrigée lors de la conversion du code, car ce n’est généralement pas ce que les développeurs ont l’intention de modifier.
Teradata : SELECT (1,00/28) * 15,00 /* donne 0,60 */
Snowflake arrondira le résultat de la division (1,00/28) * 15,00 à deux décimales : SELECT (1,00/28) * 15,00 = 0,535710 = 0,54
Division entier-entier¶
Lors de la division de deux valeurs entières, Teradata effectue une troncation (floor), tandis que Snowflake effectue un arrondi. Pour maintenir un comportement cohérent pendant la migration, la conversion automatisée du code ajoute automatiquement une instruction TRUNC dans ces cas.
Teradata : SELECT (5/3) = 1 /donne 1 puisque la division entière arrondit à l’inférieur/
Snowflake : en divisant 5 par 3, on obtient 1,6666666, qui s’arrondit à 2
Division tronquée dans Snowflake : SELECT TRUNC(5/3) donne 1
Arrondi bancaire¶
Teradata propose l’arrondi bancaire via le paramètre ROUNDHALFWAYMAGUP, tandis que Snowflake utilise uniquement des méthodes d’arrondi standard.
SQL |
Teradata |
Snowflake |
---|---|---|
CAST(1.05 AS DECIMAL(9,1)) |
<mark style= »background-color:orange; »>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 |
Conversion de décimaux en entiers¶
Teradata et Snowflake traitent différemment les valeurs décimales. Alors que Teradata tronque les valeurs décimales, Snowflake les arrondit à l’entier le plus proche. Pour maintenir la cohérence avec le comportement de Teradata, le processus de conversion ajoute automatiquement une instruction TRUNC.
SQL |
Teradata |
Snowflake |
---|---|---|
CAST(<mark style= »background-color:blue;>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 |
Nombre sans précision/échelle¶
Lorsqu’une colonne Teradata NUMBER est définie sans spécifier d’échelle ou de précision, elle peut stocker des valeurs décimales avec une échelle variable (de 0 à 38), tant que la précision totale reste inférieure à 38 chiffres. Cependant, Snowflake exige des valeurs d’échelle et de précision fixes pour les colonnes NUMBER. Voici un exemple de la façon dont les nombres sont définis dans une table Teradata avec ce format flexible :
CREATE MULTISET TABLE DATABASEXYZ.TABLE_NUMS
(NUM_COL1 NUMBER(*),
NUM_COL2 NUMBER,
NUM_COL3 NUMBER(38,*));
La table suivante montre deux exemples de valeurs qui dépassent les limites de taille de colonne de Snowflake. Ces valeurs peuvent apparaître dans n’importe quelle colonne de Teradata présentée précédemment.
Valeur 1 : 123 345 678 901 234 567 891 012,0123456789
Valeur 2 : 123,12345678901234567890
Ces valeurs numériques nécessiteraient un type de données NUMBER(42, 20), ce qui dépasse la limite de précision maximale de 38 fixée par Snowflake. Snowflake travaille actuellement à la mise en place d’une fonctionnalité de précision et d’échelle flexible.
Troncation sur INSERT pour les instructions SQL DML¶
Teradata tronque automatiquement les valeurs de chaîne qui dépassent la longueur de champ définie lors de l’insertion. Alors que SnowConvert conserve la même longueur de champ pendant la conversion (par exemple, VARCHAR(20) reste VARCHAR(20)), Snowflake ne tronque pas automatiquement les chaînes trop grandes. Si votre processus d’ingestion des données dépend de la troncation automatique, vous devrez le modifier manuellement en ajoutant une fonction LEFT(). SnowConvert n’ajoute pas intentionnellement la troncation automatiquement en raison de l’impact potentiel sur l’ensemble de la base de code.
Exemple d’émission par défaut d’un flottant :¶
/* <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 ****/
);
Agrégation de données flottantes¶
Les nombres à virgule flottante sont des représentations approximatives des valeurs décimales. En raison de ces approximations, différents systèmes de base de données peuvent produire des résultats légèrement différents lorsqu’ils effectuent des calculs et des agrégations avec des types de données flottantes. Cette variation est due au fait que chaque système de base de données gère l’arithmétique à virgule flottante et l’arrondi à sa manière.
Autres considérations¶
Élimination des jointures¶
Snowflake exécute les requêtes SQL exactement comme elles sont écrites, y compris toutes les jointures spécifiées, qu’elles affectent ou non les résultats finaux. Contrairement à Snowflake, Teradata peut supprimer automatiquement les jointures inutiles en utilisant les relations de clés primaires et étrangères définies dans la structure des tables. Cette fonction de Teradata permet principalement d’éviter les requêtes mal écrites et ne pose généralement de problème que lorsque le code a été spécifiquement écrit pour utiliser cette fonction. Si votre code existant a été conçu pour tirer parti de la fonction d’élimination des jointures de Teradata, les outils de conversion de code automatisés ne peuvent pas remédier à cette limite. Dans de tels cas, il se peut que vous deviez revoir certaines parties de votre solution.
Utilisation des fonctions de fenêtre avec max() et order by
Comportement et valeurs par défaut de Teradata :¶
Par défaut : lorsqu’une clause ORDER BY est présente mais qu’aucune clause ROWS ou ROWS BETWEEN n’est spécifiée, les fonctions d’agrégation de la fenêtre Teradata SQL utilisent automatiquement ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.
Comportement de Snowflake et valeurs par défaut :¶
Par défaut : lorsque vous utilisez une fonction d’agrégation de fenêtres avec une clause ORDER BY mais sans spécifier ROWS ou ROWS BETWEEN, Snowflake applique automatiquement ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW comme cadre de fenêtre.
Exemple :
Vous trouverez ci-dessous un exemple de table nommée TEST_WIN qui présente les données salariales des employés de différents services.
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 |
Le code suivant, lorsqu’il est exécuté dans Teradata, calcule le salaire le plus élevé parmi tous les employés, regroupés par département.
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 |
Lorsque vous exécutez le code converti à l’aide de Snowflake-SnowConvert, il se peut que vous constatiez des résultats différents (valeurs mises en évidence). Ces différences sont attendues et correspondent aux paramètres par défaut de 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 |
Pour obtenir des résultats identiques à ceux de Teradata, vous devez spécifier la valeur ROWS/RANGE comme indiqué dans le code ci-dessous.
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 |
La clause RANGE/ROWS définit explicitement l’ordre des lignes. Vous pouvez obtenir des résultats similaires en supprimant complètement la clause ORDER BY.
Références¶
Snowflake : https://docs.snowflake.com/en/sql-reference/functions-analytic.html Teradata : https://docs.teradata.com/r/756LNiPSFdY~4JcCCcR5Cw/dIV_fAtkK3UeUIQ5_uucQw