

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

# 查询嵌套数据
<a name="query-nested-data"></a>

AWS Clean Rooms 提供对关系和嵌套数据的与 SQL 兼容的访问权限。

AWS Clean Rooms 访问嵌套数据时，使用点符号和数组下标进行路径导航。它还启用 FROM 子句项用于遍历数组并用于取消嵌套操作。以下主题描述了不同的查询模式，这些模式将array/struct/map数据类型的使用与路径和数组导航、取消嵌套和联接相结合。

**Topics**
+ [导航](#navigation)
+ [取消嵌套查询](#unnesting-queries)
+ [宽松语义](#lax-semantics)
+ [自检类型](#types-of-introspection)

## 导航
<a name="navigation"></a>

AWS Clean Rooms 允许分别使用方`[...]`括号和点符号导航到数组和结构。此外，您还可以使用点记法将导航混合到结构中，使用括号符号将数组混合到结构中。

**Example**  
例如，以下示例查询假定 `c_orders` 数组数据列是一个具有结构的数组，并且属性名为 `o_orderkey`。  

```
SELECT cust.c_orders[0].o_orderkey FROM customer_orders_lineitem AS cust;
```

您可以在所有类型的查询中使用点和括号符号，例如筛选、联接和聚合。您可以在通常存在列引用的查询中使用这些符号。

**Example**  
以下示例使用筛选结果的 SELECT 语句。  

```
SELECT count(*) FROM customer_orders_lineitem WHERE c_orders[0].o_orderkey IS NOT NULL;
```

**Example**  
以下示例在 GROUP BY 和 ORDER BY 子句中使用括号和点导航：  

```
SELECT c_orders[0].o_orderdate,
       c_orders[0].o_orderstatus,
       count(*)
FROM customer_orders_lineitem
WHERE c_orders[0].o_orderkey IS NOT NULL
GROUP BY c_orders[0].o_orderstatus,
         c_orders[0].o_orderdate
ORDER BY c_orders[0].o_orderdate;
```

## 取消嵌套查询
<a name="unnesting-queries"></a>

要取消嵌套查询，请 AWS Clean Rooms 启用对数组的迭代。它通过使用查询的 FROM 子句导航数组来实现这一点。

**Example**  
使用前面的示例，以下示例对 `c_orders` 的属性值进行迭代。  

```
SELECT o FROM customer_orders_lineitem c, c.c_orders o;
```

取消嵌套语法是 FROM 子句的扩展。在标准 SQL 中，FROM 子句 `x (AS) y` 表示 `y` 迭代关系 `x` 中的每个元组。在这种情况下，`x` 指的是关系，而 `y` 指的是关系 `x` 的别名。同样，使用 FROM 子句项 `x (AS) y` 进行取消嵌套的语法表示 `y` 迭代数组表达式 `x` 中的每个值。在这种情况下，`x` 是一个数组表达式，而 `y` 是 `x` 的别名。

左侧操作数也可以使用点和括号表示法进行常规导航。

**Example**  
在上一个示例中：  
+ `customer_orders_lineitem c` 是对 `customer_order_lineitem` 基表的迭代
+ `c.c_orders o` 是对 `c.c_orders array` 的迭代
要迭代作为数组中的数组的 `o_lineitems` 属性，必须添加多个子句。



```
SELECT o, l FROM customer_orders_lineitem c, c.c_orders o, o.o_lineitems l;
```

AWS Clean Rooms 在使用遍历数组时，还支持使用数组索引 AT 关键字。子句 `x AS y AT z` 迭代数组 `x` 并生成字段 `z`，即数组索引。

**Example**  
以下示例演示数组索引的工作原理：  

```
SELECT c_name,
       orders.o_orderkey AS orderkey,
       index AS orderkey_index
FROM customer_orders_lineitem c, c.c_orders AS orders AT index 
ORDER BY orderkey_index;
c_name             | orderkey | orderkey_index
-------------------+----------+----------------
Customer#000008251 | 3020007  |        0
Customer#000009452 | 4043971  |        0  (2 rows)
```

**Example**  
以下示例对标量数组进行迭代：  

```
CREATE TABLE bar AS SELECT json_parse('{"scalar_array": [1, 2.3, 45000000]}') AS data;

SELECT index, element FROM bar AS b, b.data.scalar_array AS element AT index;

 index | element
-------+----------
     0 | 1
1 | 2.3
2 | 45000000
(3 rows)
```

**Example**  
以下示例对多个级别的数组进行迭代。该示例使用多个 unnest 子句来迭代到最内层的数组。这些区域有：`f.multi_level_array`AS 数组迭`multi_level_array`代。阵列 AS 元素是对里面数组的迭代`multi_level_array`。  

```
CREATE TABLE foo AS SELECT json_parse('[[1.1, 1.2], [2.1, 2.2], [3.1, 3.2]]') AS multi_level_array;

SELECT array, element FROM foo AS f, f.multi_level_array AS array, array AS element;

   array   | element
-----------+---------
 [1.1,1.2] | 1.1
 [1.1,1.2] | 1.2
 [2.1,2.2] | 2.1
 [2.1,2.2] | 2.2
 [3.1,3.2] | 3.1
 [3.1,3.2] | 3.2
(6 rows)
```

## 宽松语义
<a name="lax-semantics"></a>

预设情况下，在导航无效时，嵌套数据值的导航操作返回 null，而不是返回错误。如果嵌套数据值不是对象，或者嵌套数据值是一个对象，但不包含查询中使用的属性名称，则对象导航无效。

**Example**  
例如，以下查询访问嵌套数据列 `c_orders` 中的无效属性名称：  

```
SELECT c.c_orders.something FROM customer_orders_lineitem c;
```

如果嵌套数据值不是数组或数组索引超出界限，则数组导航返回 null。

**Example**  
以下查询返回 null，因为 `c_orders[1][1]` 超出了界限。  

```
SELECT c.c_orders[1][1] FROM customer_orders_lineitem c;
```

## 自检类型
<a name="types-of-introspection"></a>

嵌套数据列支持返回有关该值的类型和其他类型信息的检查函数。AWS Clean Rooms 支持以下用于嵌套数据列的布尔函数：
+ DECIMAL\$1PRECISION
+ DECIMAL\$1SCALE
+ IS\$1ARRAY 
+ IS\$1BIGINT 
+ IS\$1CHAR 
+ IS\$1DECIMAL 
+ IS\$1FLOAT 
+ IS\$1INTEGER 
+ IS\$1OBJECT 
+ IS\$1SCALAR 
+ IS\$1SMALLINT 
+ IS\$1VARCHAR 
+ JSON\$1TYPEOF 

如果输入值为 null，所有这些函数都返回 false。IS\$1SCALAR、IS\$1OBJECT 和 IS\$1ARRAY 是相互排斥的，涵盖除 null 之外的所有可能的值。要推断出与数据对应的类型，请 AWS Clean Rooms 使用 JSON\$1TYPEOF 函数，该函数返回嵌套数据值的类型（顶层），如以下示例所示：

```
SELECT JSON_TYPEOF(r_nations) FROM region_nations;
 json_typeof
 ------------- 
array
(1 row)
```

```
SELECT JSON_TYPEOF(r_nations[0].n_nationkey) FROM region_nations;
 json_typeof
 -------------
 number
```