SnowConvert: Teradata

数值数据运算

计算精度

Teradata 与 Snowflake 处理计算的方式各有不同:

  • Teradata 根据数据类型,在完成每个计算步骤之后对数字进行四舍五入:

    • 对于十进制类型,它会保持更高的精度

    • 对于 NUMBER 类型,它会保持全精度

  • Snowflake 使用 NUMBER 数据类型存储所有数字,并在整个计算过程中保持全精度。这可能会导致结果不同于 Teradata,尤其是在使用十进制、整数或浮点类型时。

这种行为差异在代码转换期间不会调整,因为开发者通常并无作出此更改的意图。

Teradata: SELECT (1.00/28) * 15.00 /* 返回 0.60 */

Snowflake 会将除法运算 (1.00/28) * 15.00 的结果舍入到小数点后两位:SELECT (1.00/28) * 15.00 = 0.535710 = 0.54

整数与整数之间的除法

将两个整数值相除时,Teradata 会执行截断(向下取整),而 Snowflake 则执行舍入。为了在迁移期间保持一致的行为,自动代码转换会在此类情况下自动添加 TRUNC 语句。

Teradata: SELECT (5/3) = 1 /* 整数除法向下舍入,因此返回 1 */

Snowflake:当 5 除以 3 时,结果为 1.6666666,舍入的结果为 2

Snowflake 中截断的除法:SELECT TRUNC(5/3) 返回 1

Banker 式舍入

Teradata 通过 ROUNDHALFWAYMAGUP 参数提供 Banker 式舍入功能,而 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

十进制到整数的转换

Teradata 与 Snowflake 处理十进制值的方式各有不同。Teradata 会截断十进制值,而 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 列,它依然可以存储小数,小数位数可在 0 至 38 之间变化,只要总精度保持在 38 位以内即可。但 Snowflake 要求 NUMBER 列使用固定的小数位数和精度值。下面的示例展示了如何使用这种灵活格式在 Teradata 表中定义数字:

CREATE MULTISET TABLE DATABASEXYZ.TABLE_NUMS
     (NUM_COL1 NUMBER(*),
      NUM_COL2 NUMBER,
      NUM_COL3 NUMBER(38,*));
Copy

下表展示了两个超过 Snowflake 列大小限制的值的示例。这些值可能出现在先前显示的任何 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 ****/
);
Copy

浮点数据聚合

浮点数是对十进制值的近似表示。由于这些近似值,使用浮点数据类型执行计算和聚合时,不同的数据库系统产生的结果可能略有不同。之所以存在这种差异,是因为每个数据库系统都以自己的方式处理浮点算术和舍入。

其他注意事项

联接消除

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 行为和默认设置:

默认设置:如果您使用带有 ORDER BY 子句的窗口聚合函数,但未指定 ROWS 或 ROWS BETWEEN,Snowflake 会自动应用 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 作为窗口框架。

示例:

以下是名为 TEST_WIN 的示例表,其中显示了各部门的员工薪资数据。

DEPT_NMDEPT_NOEMP_NOSALARY
SALES10115000
SALES10126000
HR20211000
HR20222000
PS30317000
PS30329000

以下代码在 Teradata 中执行时,会按部门分组计算所有员工中最高的工资。

SELECT DEPT_NM, SALARY ,DEPT_NO,
MAX(SALARY) OVER ( ORDER BY DEPT_NO  ) AS MAX_DEPT_SALARY
FROM TEST_WIN;
Copy
DEPT_NMSALARYDEPT_NOMAX_DEPT_SALARY
SALES6000109000
SALES5000109000
HR2000209000
HR1000209000
PS7000309000
PS9000309000

使用 Snowflake-SnowConvert 执行转换后的代码时,您可能会注意到结果有所不同(突出显示的值)。这些差异符合预期,与 Snowflake 的默认设置一致。

SELECT DEPT_NM, SALARY ,DEPT_NO,
MAX(SALARY) OVER ( ORDER BY DEPT_NO  ) AS MAX_DEPT_SALARY
FROM TEST_WIN;
Copy
DEPT_NMSALARYDEPT_NOMAX_DEPT_SALARY
SALES5000106000
SALES6000106000
HR1000206000
HR2000206000
PS7000309000
PS9000309000

要在 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;
Copy
DEPT_NMSALARYDEPT_NOMAX_DEPT_SALARY
SALES5000109000
SALES6000109000
HR1000209000
HR2000209000
PS7000309000
PS9000309000

RANGE/ROWS 子句明确定义了行的排序方式。通过完全删除 ORDER BY 子句,即可获得类似的结果。

引用

Snowflake:https://docs.snowflake.cn/en/sql-reference/functions-analytic.html Teradata:https://docs.teradata.com/r/756LNiPSFdY~4JcCCcR5Cw/dIV_fAtkK3UeUIQ5_uucQw (https://docs.teradata.com/r/756LNiPSFdY~4JcCCcR5Cw/dIV_fAtkK3UeUIQ5_uucQw)

语言: 中文