SnowConvert: Teradata¶
数値データ操作¶
計算精度¶
TeradataとSnowflakeでは、計算の扱いが異なります。
Teradataは、各計算ステップの後にデータ型に基づいて数値を丸めます。
10進数タイプでは、大きい方の精度を維持します。
NUMBER タイプの場合は、完全な精度を保ちます。
Snowflakeはすべての数値を NUMBER データ型を使用して格納し、計算中も完全な精度を維持します。このため、特に10進数、整数、浮動小数点タイプを扱う場合、Teradataとは異なる結果になることがあります。
この動作の違いは、通常、開発者が意図して変更するものではないため、コード変換時に調整されることはありません。
Teradata: SELECT (1.00/28) * 15.00 /* 0.60を返します */
Snowflakeは除算の結果 (1.00/28) * 15.00を小数点以下2桁に丸めます。 SELECT (1.00/28) * 15.00 = 0.535710 = 0.54
整数-整数除算¶
2つの整数値を除算する場合、Teradataは切り捨て(フロア)、Snowflakeは丸めます。移行中の一貫した動作を維持するために、自動コード変換ではこのような場合に TRUNC ステートメントを自動的に追加します。
Teradata: SELECT (5/3) = 1 /* 整数の除算は切り捨てられるため1になります */
Snowflake: 5を3で除算すると1.6666666となり、2に丸められます。
Snowflakeの切り捨て除算: SELECT TRUNC(5/3) は1を返します。
銀行丸め¶
Teradataは、 ROUNDHALFWAYMAGUP パラメーターを通じて銀行丸めを提供しますが、Snowflakeは標準的な丸め方法のみを使用します。
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 |
10進数から整数への変換¶
TeradataとSnowflakeでは10進数の扱いが異なります。Teradataは10進数の値を切り捨てますが、Snowflakeは最も近い整数に丸めます。Teradataの動作との一貫性を保つため、変換処理では自動的に 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 |
精度/スケールを含まない数値¶
Teradata NUMBER 列がスケールや精度を指定せずに定義されている場合、合計精度が38桁以内であれば、さまざまなスケール(0から38まで)の10進数値を格納することができます。しかし、Snowflakeでは、 NUMBER 列のスケールと精度の値が固定されている必要があります。この柔軟な形式を持つTeradataテーブルで数値がどのように定義されるかの例を示します。
CREATE MULTISET TABLE DATABASEXYZ.TABLE_NUMS
(NUM_COL1 NUMBER(*),
NUM_COL2 NUMBER,
NUM_COL3 NUMBER(38,*));
次のテーブルは、Snowflakeの列サイズ制限を超える値の2つの例を示しています。これらの値は、先に示したTeradataの列のいずれかに表示される可能性があります。
値1: 123,345,678,901,234,567,891,012.0123456789
値2: 123.12345678901234567890
これらの数値は、 NUMBER(42, 20) データ型を必要とし、Snowflakeの最大精度制限である38を超えます。Snowflakeは現在、柔軟な精度とスケール機能の実装に取り組んでいます。
SQL DML ステートメントの INSERT での切り捨て¶
Teradataは、挿入時に定義されたフィールド長を超える文字列値を自動的に切り捨てます。SnowConvert は変換中も同じフィールド長を維持しますが(例: VARCHAR(20)は VARCHAR(20)のまま)、Snowflakeはサイズの大きい文字列を自動的に切り捨てません。データインジェスチョン処理が自動切り捨てに依存している場合は、 LEFT()関数を追加して手動で変更する必要があります。コードベース全体に影響を及ぼす可能性があるため、 SnowConvert が意図的に切り捨てを自動で追加することはありません。
浮動小数点数のデフォルトの問題例:¶
/* <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 ****/
);
浮動小数点数データ集計¶
浮動小数点数は10進数の近似値です。このような近似値のため、データベースシステムが異なると、浮動小数点データ型で計算や集計を実行したときのパフォーマンスが若干異なる場合があります。このようなばらつきが生じるのは、データベースシステムがそれぞれ独自の方法で浮動小数点演算と丸めを処理するためです。
その他の考慮事項¶
結合除去¶
Snowflakeは、指定されたすべての結合を含め、最終結果への影響の有無にかかわらず、 SQL クエリを記述されたとおりに実行します。Snowflakeとは異なり、Teradataはテーブル構造で定義された主キーと外部キーの関係を使用して、不要な結合を自動的に削除することができます。Teradataのこの機能は、主に稚拙な記述のクエリを防ぐのに役立ち、通常、この機能を使用するために特別に書かれたコードでのみ懸念されます。既存のコードがTeradataの結合除去機能を利用するように設計されている場合、自動コード変換ツールではこの制限に対処できません。そのような場合、ソリューションの一部を再設計することが必要になる場合があります。
max()およびorder byのあるウィンドウ関数の使用
Teradataの動作とデフォルト:¶
デフォルト: ORDER BY 句が存在し、 ROWS または ROWS BETWEEN 句が指定されていない場合、Teradata SQL ウィンドウ集計関数は自動的に ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING を使用します。
Snowflakeの動作とデフォルト:¶
デフォルト: ROWS または ROWS BETWEEN を指定せずに ORDER BY 句を指定してウィンドウ集計関数を使用すると、Snowflakeは自動的にウィンドウフレームとして ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW を適用します。
例:
以下は、さまざまな部門での従業員の給与データを示す TEST_WIN という名前のサンプルテーブルです。
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 |
以下のコードをTeradataで実行すると、部門別にグループ化された全従業員の中で最も高い給与が計算されます。
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 |
変換したコードをSnowflake-SnowConvert で実行すると、異なる結果(ハイライトされた値)が表示される場合があります。これらの違いは予想されたことであり、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 |
Teradataと同じ結果を得るには、以下のコードのように ROWS/RANGE の値を指定する必要があります。
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 |
RANGE/ROWS 句は、行の順序を明示的に定義します。ORDER BY 句を完全に削除しても同様の結果を得ることができます。
参照¶
Snowflake: https://docs.snowflake.com/en/sql-reference/functions-analytic.html Teradata: https://docs.teradata.com/r/756LNiPSFdY~4JcCCcR5Cw/dIV_fAtkK3UeUIQ5_uucQw