

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 将 Teradata RESET WHEN 功能转换为 Amazon Redshift SQL
<a name="convert-the-teradata-reset-when-feature-to-amazon-redshift-sql"></a>

*Po Hong，Amazon Web Services*

## Summary
<a name="convert-the-teradata-reset-when-feature-to-amazon-redshift-sql-summary"></a>

**RESET WHEN**是 SQL 分析窗口函数中使用的 Teradata 功能。它是 ANSI SQL 标准的扩展。**RESET WHEN** 根据某些指定条件确定 SQL 窗口函数在其上运行的分区。如果条件计算结果为 **TRUE**，则会在现有窗口分区内创建新的动态子分区。有关 **RESET WHEN** 的更多信息，请参阅 [Teradata 文档](https://docs.teradata.com/reader/1DcoER_KpnGTfgPinRAFUw/b7wL86OoMTPno6hrSPNdDg)。

Amazon Redshift 不支持 SQL 窗口函数中的 **RESET WHEN**。若要实现此功能，您必须将 **RESET WHEN** 转换为 Amazon Redshift 中的原生 SQL 语法，并使用多个嵌套函数。此模式演示了如何使用 Teradata **RESET WHEN** 功能以及如何将其转换为 Amazon Redshift SQL 语法。 

## 先决条件和限制
<a name="convert-the-teradata-reset-when-feature-to-amazon-redshift-sql-prereqs"></a>

**先决条件**
+ Teradata 数据仓库及其 SQL 语法的基础知识
+ 对 Amazon Redshift 及其 SQL 语法有很好的了解

## 架构
<a name="convert-the-teradata-reset-when-feature-to-amazon-redshift-sql-architecture"></a>

**源技术堆栈**
+ Teradata 数据仓库

**目标技术堆栈**
+ Amazon Redshift

**架构**

有关将 Teradata 数据库迁移至 Amazon Redshift 的高级架构，请参阅使用 AWS SCT 数据提取代理[将 Teradata 数据库迁移至 Amazon Redshift](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/migrate-a-teradata-database-to-amazon-redshift-using-aws-sct-data-extraction-agents.html)模式。迁移不会自动将 Teradata **NORMALIZE** 短语转换为 Amazon Redshift SQL。您可以按照下一节中的指导原则转换此 Teradata 扩展。

## 工具
<a name="convert-the-teradata-reset-when-feature-to-amazon-redshift-sql-tools"></a>

**代码**

为了说明 **RESET WHEN** 的概念，请考虑 Teradata 中的下表定义：

```
create table systest.f_account_balance                                
( account_id integer NOT NULL,
  month_id integer,
  balance integer )
unique primary index (account_id, month_id);
```

运行以下 SQL 代码，以将示例数据插入表中：

```
BEGIN TRANSACTION;
Insert Into systest.f_account_balance values (1,1,60);
Insert Into systest.f_account_balance values (1,2,99);
Insert Into systest.f_account_balance values (1,3,94);
Insert Into systest.f_account_balance values (1,4,90);
Insert Into systest.f_account_balance values (1,5,80);
Insert Into systest.f_account_balance values (1,6,88);
Insert Into systest.f_account_balance values (1,7,90);
Insert Into systest.f_account_balance values (1,8,92);
Insert Into systest.f_account_balance values (1,9,10);
Insert Into systest.f_account_balance values (1,10,60);
Insert Into systest.f_account_balance values (1,11,80);
Insert Into systest.f_account_balance values (1,12,10);
END TRANSACTION;
```

该示例表具有以下数据：


| 
| 
| account\$1id | month\$1id | balance | 
| --- |--- |--- |
| 1 | 1 | 60 | 
| 1 | 2 | 99 | 
| 1 | 3 | 94 | 
| 1 | 4 | 90 | 
| 1 | 5 | 80 | 
| 1 | 6 | 88 | 
| 1 | 7 | 90 | 
| 1 | 8 | 92 | 
| 1 | 9 | 10 | 
| 1 | 10 | 60 | 
| 1 | 11 | 80 | 
| 1 | 12 | 10 | 

对于每个账户，假设您想要分析每月余额连续增加的顺序。当一个月的余额小于或等于上个月的余额时，要求将计数器重置为零，并重新启动。

*Teradata RESET WHEN 用例*

若要分析此数据，Teradata SQL 使用了带有嵌套聚合和 **RESET WHEN** 短语的窗口函数，如下所示：

```
SELECT account_id, month_id, balance,
 ( ROW_NUMBER() OVER (PARTITION BY account_id ORDER BY month_id
RESET WHEN balance <= SUM(balance) over (PARTITION BY account_id ORDER BY month_id ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) ) -1 ) as balance_increase
FROM systest.f_account_balance
ORDER BY 1,2;
```

输出：


| 
| 
|  account\$1id | month\$1id | balance | balance\$1increase | 
| --- |--- |--- |--- |
| 1 | 1 | 60 | 0 | 
| 1 | 2 | 99 | 1 | 
| 1 | 3 | 94 | 0 | 
| 1 | 4 | 90 | 0 | 
| 1 | 5 | 80 | 0 | 
| 1 | 6 | 88 | 1 | 
| 1 | 7 | 90 | 2 | 
| 1 | 8 | 92 | 3 | 
| 1 | 9 | 10 | 0 | 
| 1 | 10 | 60 | 1 | 
| 1 | 11 | 80 | 2 | 
| 1 | 12 | 10 | 0 | 

在 Teradata 中，查询处理方式如下：

1. **SUM（余额）**汇总函数计算给定账户在给定月份内所有余额的总和。

1. 我们会检查给定月份（给定账户）的余额是否大于上个月的余额。

1. 如果余额增加，我们将跟踪累积计数值。如果 **RESET WHEN** 条件的计算结果为 **false**，这意味着余额在连续几个月中有所增加，则我们会继续增加计数。

1. **ROW\$1NUMBER ()** 有序分析函数计算计数值。当我们一个月的余额小于或等于前一个月的余额时，**RESET WHEN** 条件的计算结果为 **true**。如果是这样，我们启动一个新分区，**ROW\$1NUMBER()** 从 1 重新开始计数。我们使用 **ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING** 来访问前一行的值。

1. 我们减去 1，以确保计数值以 0 开头。

*Amazon Redshift 等效 SQL*

Amazon Redshift 不支持 SQL 分析窗口函数中的 **RESET WHEN** 短语。 若要生成相同的结果，您必须使用 Amazon Redshift 原生 SQL 语法和嵌套子查询重写 Teradata SQL，如下所示： 

```
SELECT account_id, month_id, balance,
   (ROW_NUMBER() OVER(PARTITION BY account_id, new_dynamic_part ORDER BY month_id) -1) as balance_increase
FROM
( SELECT account_id, month_id, balance, prev_balance,
SUM(dynamic_part) OVER (PARTITION BY account_id ORDER BY month_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) As new_dynamic_part
FROM ( SELECT account_id, month_id, balance,
SUM(balance) over (PARTITION BY account_id ORDER BY month_id ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) as prev_balance,
(CASE When balance <= prev_balance Then 1 Else 0 END) as dynamic_part
FROM systest.f_account_balance ) A
) B
ORDER BY 1,2;
```

由于 Amazon Redshift 不支持单个 SQL 语句的 **SELECT** 子句中的嵌套窗口函数，因此您必须使用两个嵌套的子查询。
+ 在内部子查询(别名 A)中，创建并填充动态分区指示器 (**dynamic\$1part**)。如果一个月的余额小于或等于前一个月的余额，则 **dynamic\$1part** 设置为 1；否则，设置为 0。 
+ 在下一层(别名 B)中，将生成 **new\$1dynamic\$1part** 属性作为 **SUM** 窗口函数的结果。 
+ 最后，将 **new\$1dynamic\$1part** 作为新的分区属性（**dynamic partition**）添加到现有分区属性（**account\$1id**）中，并应用与 Teradata 中相同的 **ROW\$1NUMBER() **窗口函数（减一）。 

进行上述更改后，Amazon Redshift SQL 生成的输出与 Teradata 相同。

## 操作说明
<a name="convert-the-teradata-reset-when-feature-to-amazon-redshift-sql-epics"></a>

### 将 RESET WHEN 转换为 Amazon Redshift SQL
<a name="convert-reset-when-to-amazon-redshift-sql"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建 Teradata 窗口函数。 | 根据需求使用嵌套聚合与 RESET WHEN 短语。 | SQL Developer | 
| 将代码转换为 Amazon Redshift SQL。 | 若要转换您的代码，请按照此模式的“工具”部分中的指南进行操作。 | SQL Developer | 
| 在 Amazon Redshift 中运行代码。 | 创建您的表，将数据加载至表中，然后在 Amazon Redshift 中运行您的代码。 | SQL Developer | 

## 相关资源
<a name="convert-the-teradata-reset-when-feature-to-amazon-redshift-sql-resources"></a>

**参考**
+ [RESET WHEN 短语](https://docs.teradata.com/reader/1DcoER_KpnGTfgPinRAFUw/b7wL86OoMTPno6hrSPNdDg)（Teradata 文档）
+ [RESET WHEN 解释](https://stackoverflow.com/questions/53344536/teradata-reset-when-partition-by-order-by)（堆栈溢出）
+ [迁移至 Amazon Redshift](https://aws.amazon.com/redshift/data-warehouse-migration/)（AWS 网站）
+ [使用 AWS SCT 数据提取代理，将 Teradata 数据库迁移至 Amazon Redshift](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/migrate-a-teradata-database-to-amazon-redshift-using-aws-sct-data-extraction-agents.html) (AWS Prescriptive Guidance)
+ [将 Teradata RESET WHEN 时态功能转换至 Amazon Redshift SQL](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/convert-the-teradata-normalize-temporal-feature-to-amazon-redshift-sql.html) (AWS Prescriptive Guidance)

**工具**
+ [AWS Schema Conversion Tool (AWS SCT)](https://aws.amazon.com/dms/schema-conversion-tool/)

**合作伙伴**
+ [AWS Migration Competency Partners](https://aws.amazon.com/migration/partner-solutions/#delivery)