

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

# 使用标量 Python UDF 为 Amazon Redshift 查询结果设置特定于语言的排序
<a name="set-up-language-specific-sorting-for-amazon-redshift-query-results-using-a-scalar-python-udf"></a>

*Ethan Stark，Amazon Web Services*

## Summary
<a name="set-up-language-specific-sorting-for-amazon-redshift-query-results-using-a-scalar-python-udf-summary"></a>

此模式提供了使用标量 Python UDF（用户定义的函数）为 Amazon Redshift 查询结果设置不区分大小写的语言排序的步骤和示例代码。有必要使用标量 Python UDF，因为 Amazon Redshift 返回基于二进制 UTF-8 排序的结果，并且不支持特定于语言的排序。Python UDF 是基于 Python 程序并在数据仓库运行的非 SQL 处理代码。您可在单个查询中使用 SQL 语句运行 Python UDF 代码。有关更多信息，请参阅[亚马逊 Redshift AWS 大数据 UDFs 中的 Python 简介](https://aws.amazon.com/blogs/big-data/introduction-to-python-udfs-in-amazon-redshift/)博客文章。

此模式中的示例数据基于土耳其字母表，用于演示目的。此模式中的标量 Python UDF 旨在使 Amazon Redshift 的默认查询结果符合土耳其语字符的语言顺序。有关更多信息，请参阅此模式的*其他信息*部分中的*土耳其语示例*。您可以用这种模式修改其他语言标量 Python UDF。

## 先决条件和限制
<a name="set-up-language-specific-sorting-for-amazon-redshift-query-results-using-a-scalar-python-udf-prereqs"></a>

**先决条件**
+ 带有数据库、架构和表的 [Amazon Redshift 集群](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html)
+ 具有 `CREATE TABLE` 和 `CREATE FUNCTION` 权限的 [Amazon Redshift 用户](https://docs.aws.amazon.com/redshift/latest/dg/r_Users.html)
+ [Python 2.7](https://www.python.org/download/releases/2.7/) 或更高版本

**限制**

此模式中的查询使用的语言排序不区分大小写。

## 工具
<a name="set-up-language-specific-sorting-for-amazon-redshift-query-results-using-a-scalar-python-udf-tools"></a>

**AWS 服务**
+ [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/gsg/getting-started.html) 是一项在 AWS 云中托管的 PB 级数据仓库服务。Amazon Redshift 与数据湖集成，让您可以使用数据获得对您的业务和客户的新见解。

**其他工具**
+ [Python (UDFs) 用户定义的函数](https://docs.snowflake.com/en/developer-guide/udf/python/udf-python-introduction.html)是可以用 Python 编写然后在 SQL 语句中调用的函数。

## 操作说明
<a name="set-up-language-specific-sorting-for-amazon-redshift-query-results-using-a-scalar-python-udf-epics"></a>

### 开发代码以按语言顺序对查询结果进行排序
<a name="develop-code-to-sort-query-results-in-linguistic-order"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 为您的示例数据创建一个表。 | 要在 Amazon Redshift 中创建表并将示例数据插入到该表中，请使用以下 SQL 语句：<pre>CREATE TABLE my_table (first_name varchar(30));<br /><br />INSERT INTO my_table (first_name)<br />VALUES<br />    ('ali'),<br />    ('Ali'),<br />    ('ırmak'),<br />    ('IRMAK'),<br />    ('irem'),<br />    ('İREM'),<br />    ('oğuz'),<br />    ('OĞUZ'),<br />    ('ömer'),<br />    ('ÖMER'),<br />    ('sedat'),<br />    ('SEDAT'),<br />    ('şule'),</pre>示例数据中的名字包含土耳其字母表中的特殊字符。有关此示例中土耳其语注意事项的更多信息，请参阅此模式的*其他信息*部分中的*土耳其语示例*。 | 数据工程师 | 
| 检查样本数据默认排序。 | 若要在 Amazon Redshift 中查看示例数据的默认排序，请运行以下查询：<pre>SELECT first_name FROM my_table ORDER BY first_name;</pre>该查询返回您之前创建表中的名字列表：<pre>first_name<br />---------------<br />Ali<br />IRMAK<br />OĞUZ<br />SEDAT<br />ali<br />irem<br />oğuz<br />sedat<br />ÖMER<br />ömer<br />İREM<br />ırmak<br />ŞULE<br />şule</pre>查询结果的顺序不正确，因为默认二进制 UTF-8 排序不适应土耳其语特殊字符的语言顺序。 | 数据工程师 | 
| 创建标量 Python UDF。 | 若要创建标量 Python UDF，请使用以下 SQL 代码： <pre>CREATE OR REPLACE FUNCTION collate_sort (value varchar) <br />RETURNS varchar <br />IMMUTABLE <br />AS <br />$$    <br />    def sort_str(val):<br />        import string<br />        <br />        dictionary = {<br />            'I': 'ı', <br />            'ı': 'h~', <br />            'İ': 'i', <br />            'Ş': 's~', <br />            'ş': 's~', <br />            'Ğ': 'g~', <br />            'ğ': 'g~', <br />            'Ü': 'u~', <br />            'ü': 'u~', <br />            'Ö': 'o~', <br />            'ö': 'o~', <br />            'Ç': 'c~', <br />            'ç': 'c~'<br />        }<br />        <br />        for key, value in dictionary.items():<br />            val = val.replace(key, value)<br />        <br />        return val.lower()<br /> <br />    return sort_str(value)<br />    <br />$$ LANGUAGE plpythonu;</pre> | 数据工程师 | 
| 查询示例数据。 | 若要使用 Python UDF 查询示例数据，请运行以下 SQL 查询：<pre>SELECT first_name FROM my_table ORDER BY collate_sort(first_name);</pre>现在，查询以土耳其语顺序返回示例数据：<pre>first_name<br />---------------<br />ali<br />Ali<br />ırmak<br />IRMAK<br />irem<br />İREM<br />oğuz<br />OĞUZ<br />ömer<br />Ömer<br />sedat<br />SEDAT<br />şule<br />ŞULE</pre> | 数据工程师 | 

## 相关资源
<a name="set-up-language-specific-sorting-for-amazon-redshift-query-results-using-a-scalar-python-udf-resources"></a>
+ [ORDER BY 子句](https://docs.aws.amazon.com/redshift/latest/dg/r_ORDER_BY_clause.html)（Amazon Redshift 文档）
+ [创建标量 Python UDF](https://docs.aws.amazon.com/redshift/latest/dg/udf-creating-a-scalar-udf.html)（Amazon Redshift 文档）

## 附加信息
<a name="set-up-language-specific-sorting-for-amazon-redshift-query-results-using-a-scalar-python-udf-additional"></a>

**土耳其语示例**

Amazon Redshift 根据二进制 UTF-8 排序顺序（而不是特定于语言的排序顺序）返回查询结果。这意味着，如果您查询包含土耳其语字符的 Amazon Redshift 表，则查询结果不会根据土耳其语的语言顺序进行排序。土耳其语包含六个不出现在拉丁字母表中的特殊字符 (ç、ı、ğ、 ö、ş, 以及 ü)。这些特殊字符放置在基于二进制 UTF-8 排序的排序结果集的末尾，如下表所示。


| 
| 
| 二进制 UTF-8 排序 | 土耳其语语言排序 | 
| --- |--- |
| a | a | 
| b | b | 
| c | c | 
| d | **ç (\$1)** | 
| e | d | 
| f | e | 
| g | f | 
| h | g | 
| i | **ğ (\$1)** | 
| j | h | 
| k | **ı (\$1)** | 
| l | i | 
| m | j | 
| n | k | 
| o | l | 
| p | m | 
| r | n | 
| s | o | 
| t | **ö (\$1)** | 
| u | p | 
| v | r | 
| y | s | 
| z | **ş (\$1)** | 
| **ç (\$1)** | t | 
| **ğ (\$1)** | u | 
| **ı (\$1)** | **ü (\$1)** | 
| **ö (\$1)** | v | 
| **ş (\$1)** | y | 
| **ü (\$1)** | z | 

**注意**  
星号（\$1）表示土耳其语的特殊字符。

如上表所示，特殊字符 **ç** 在土耳其语语言排序中介于 **c** 和 **d** 之间，但在二进制 UTF-8 排序中在 **z** 之后。此模式中的标量 Python UDF 使用以下字符替换目录将土耳其语特殊字符替换为相应的拉丁语等效字符。


| 
| 
| 土耳其语特殊字符 | 拉丁语等效字符 | 
| --- |--- |
| ç | c\$1 | 
| ı | h\$1 | 
| ğ | g\$1 | 
| ö | o\$1 | 
| ş | s\$1 | 
| ü | u\$1 | 

**注意**  
波形符（\$1）字符附加到拉丁字符的末尾，以替换相应的土耳其语特殊字符。

**修改标量 Python UDF 函数**

要从此模式修改标量 Python UDF 函数，以便该函数接受定位参数并支持多事务字典，请使用以下 SQL 代码：

```
CREATE OR REPLACE FUNCTION collate_sort (value varchar, locale varchar) 
RETURNS varchar 
IMMUTABLE 
AS 
$$    
    def sort_str(val):
       import string
       # Turkish Dictionary
       if locale == 'tr-TR':
            dictionary = {
               'I': 'ı', 
               'ı': 'h~', 
               'İ': 'i', 
               'Ş': 's~', 
               'ş': 's~', 
               'Ğ': 'g~', 
               'ğ': 'g~', 
               'Ü': 'u~', 
               'ü': 'u~', 
               'Ö': 'o~', 
               'ö': 'o~', 
               'Ç': 'c~', 
               'ç': 'c~'
        }
        # German Dictionary
        if locale == 'de-DE':
            dictionary = {
               ....
               ....
        }
        
        for key, value in dictionary.items():
            val = val.replace(key, value)
        
        return val.lower()
 
    return sort_str(value)
    
$$ LANGUAGE plpythonu;
```

以下示例代码展示了如何查询修改后的 Python UDF：

```
SELECT first_name FROM my_table ORDER BY collate_order(first_name, 'tr-TR');
```