

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

# Query
<a name="sql-reference-query"></a>

## 语法
<a name="sql-reference-query-syntax"></a>

```
 <query> :=
     <select>
   | <query> <set-operator> [ ALL ] <query>
   | VALUES <row-constructor> { , <row-constructor> }...
   | '(' <query> ')'
  <set-operator> :=
     EXCEPT
   | INTERSECT
   | UNION
  <row-constructor> :=
     [ ROW ] ( <expression> { , <expression> }... )
```

## 选择
<a name="sql-reference-query-select"></a>

上图中的选择框代表任何 SELECT 命令；该命令在其自己的页面上有详细描述。

集合运算符（EXCEPT、INTERSECT、UNION）

集合运算符使用集合运算来组合查询生成的行：
+ EXCEPT 返回在第一个集合中但不在第二个集合中的所有行
+ INTERSECT 返回同时在第一个和第二个集合中的所有行
+ UNION 返回在任一集合中的所有行

在所有情况下，这两个集合的列数必须相同，并且列类型必须可以兼容分配。生成的关系的列名称是第一个查询的列名称。

使用 ALL 关键字后，运算符将使用数学上的[多重集合](https://en.wikipedia.org/wiki/Multiset)的语义，这意味着不会消除重复的行。例如，如果某行在第一个集合中出现 5 次，在第二个集合中出现 2 次，则 UNION ALL 将生成该行 3 \$1 2 = 5 次。

当前不支持 ALL 使用 EXCEPT 或 INTERSECT。

所有运算符都是左关联的，INTERSECT 的优先级高于 EXCEPT 或 UNION，后两者的优先级相同。要覆盖默认优先级，您可以使用圆括号。例如：

```
SELECT * FROM a
UNION
SELECT * FROM b
INTERSECT
SELECT * FROM c
EXCEPT
SELECT * FROM d
EXCEPT
SELECT * FROM E
```

相当于完全带圆括号的查询

```
( ( SELECT * FROM a
    UNION
    ( SELECT * FROM b
      INTERSECT
      SELECT * FROM c) )
  EXCEPT
  SELECT * FROM d )
EXCEPT
SELECT * FROM e
```

## 流式集合运算符
<a name="sql-reference-query-streaming-set-operators"></a>

UNION ALL 是唯一可以应用于流的集合运算符。该运算符的两边都必须是流；如果一边是流，另一边是关系，则会出错。

例如，以下查询生成通过电话或网络下达的订单流：

```
SELECT STREAM *
  FROM PhoneOrders
UNION ALL
SELECT STREAM *
  FROM WebOrders
```

行时间生成。流式 UNION ALL 生成的行的行时间与输入行的时间戳相同。

行时间边界：行时间边界是关于流的未来内容的断言。它指出流中的下一行将具有不早于边界值的 ROWTIME。例如，如果行时间边界是 2018-12-0223:23:07，则这告诉系统下一行将不早于 2018-12-0223:23:07 到达。行时间边界可用于管理数据流中的间隙，例如证券交易所过夜的间隙。

Amazon Kinesis Data Analytics 通过按时间戳合并传入行，确保 ROWTIME 列为升序。如果第一个集合的行的行时间戳为 10:00 和 10:30，第二个集合只到达 10:15，Kinesis Data Analytics 会暂停第一个集合，并等待第二个集合到达 10:30。在这种情况下，如果第二个集合的生成者发送一个行时间边界，那将是有利的。

## VALUES 运算符
<a name="sql-reference-query-values-operator"></a>

VALUES 运算符表示查询中的常量关系。（另请参阅本指南 SELECT 主题中对 VALUES 的讨论。）

VALUES 可用作顶级查询，如下所示：

```
VALUES 1 + 2 > 3;
EXPR$0
======
FALSE
VALUES
    (42, 'Fred'),
    (34, 'Wilma');
EXPR$0 EXPR$1
====== ======
    42 Fred
    34 Wilma
```

请注意，系统已为匿名表达式生成任意列名称。您可以通过将 VALUES 放入子查询并使用 AS 子句来分配列名称：

```
SELECT *
FROM (
    VALUES
        (42, 'Fred'),
        (34, 'Wilma')) AS t (age, name);
AGE NAME
=== =====
 42 Fred
 34 Wilma
```