SELECT

SELECT 可以用作语句或其他语句中的子句:

  • 作为语句,SELECT 语句是最常执行的 SQL 语句,它查询数据库并检索一组行。

  • 作为子句,SELECT 定义查询返回的列集。

另请参阅:

查询语法

语法

以下部分介绍此命令的语法:

选择所有列

[ ... ]
SELECT [ { ALL | DISTINCT } ]
       [ TOP <n> ]
       [{<object_name>|<alias>}.]*

       [ ILIKE '<pattern>' ]

       [ EXCLUDE
         {
           <col_name> | ( <col_name>, <col_name>, ... )
         }
       ]

       [ REPLACE
         {
           ( <expr> AS <col_name> [ , <expr> AS <col_name>, ... ] )
         }
       ]

       [ RENAME
         {
           <col_name> AS <col_alias>
           | ( <col_name> AS <col_alias>, <col_name> AS <col_alias>, ... )
         }
       ]
Copy

您可以在 SELECT * 之后指定以下关键字组合。关键字必须按如下所示的顺序排列:

SELECT * ILIKE ... REPLACE ...
Copy
SELECT * ILIKE ... RENAME ...
Copy
SELECT * ILIKE ... REPLACE ... RENAME ...
Copy
SELECT * EXCLUDE ... REPLACE ...
Copy
SELECT * EXCLUDE ... RENAME ...
Copy
SELECT * EXCLUDE ... REPLACE ... RENAME ...
Copy
SELECT * REPLACE ... RENAME ...
Copy

选择特定列

[ ... ]
SELECT [ { ALL | DISTINCT } ]
       [ TOP <n> ]
       {
         [{<object_name>|<alias>}.]<col_name>
         | [{<object_name>|<alias>}.]$<col_position>
         | <expr>
       }
       [ [ AS ] <col_alias> ]
       [ , ... ]
[ ... ]
Copy

列的列表支持尾随逗号。例如,支持以下 SELECT 语句:

SELECT emp_id,
       name,
       dept,
  FROM employees;
Copy

有关 SELECT 语句和语句内其他子句的更多信息,请参阅 查询语法

参数

ALL | DISTINCT

指定是否对结果集执行重复消除:

  • ALL 包括结果集中的所有值。

  • DISTINCT 消除结果集中的重复值。

默认:ALL

TOP n

指定要返回的最大结果数。请参阅 TOP <n>

object_name . alias

按照 FROM 子句中定义,指定对象标识符或对象别名。

*

星号是简写,指明输出应包括指定对象的所有列,或者所有对象的所有列(如果 * 未使用对象名称或别名限定)。在对象上执行 DESCRIBE 命令后,这些列会按显示的顺序返回。

指定 * 时,您还可以指定 ILIKEEXCLUDEREPLACERENAME

ILIKE 'pattern'

指定结果中只应包含匹配 pattern 的列。

pattern 中,您可以使用以下 SQL 通配符:

  • 使用下划线(_)匹配任何单个字符。

  • 使用百分号(%)匹配任何包含零个或多个字符的序列。

要匹配列名中任意位置的序列,请以 % 作为模式开始和结尾。

匹配不区分大小写。

如果没有列与指定的模式匹配,则会发生编译错误 (001080 (42601): ... SELECT with no columns)。

EXCLUDE col_name . EXCLUDE (col_name, col_name, ...)

指定应从结果中排除的列。

如果您要从多个表中进行选择,请使用 SELECT table_name.* 指定要从特定表中选择所有列,并在 EXCLUDE 中指定非限定列名。例如:

SELECT table_a.* EXCLUDE column_in_table_a ,
  table_b.* EXCLUDE column_in_table_b
  ...
Copy
REPLACE (expr AS col_name [ , expr AS col_name, ...] )

col_name 的值替换为计算表达式的 expr 值。

例如,要在 'DEPT-' 列中的值前面追加字符串 department_id,请使用:

SELECT * REPLACE ('DEPT-' || department_id AS department_id) ...
Copy

对于 col_name

  • 该列必须存在,并且不能由 ILIKEEXCEPT 筛选掉。

  • 您不能在替换列表中多次指定同一列。

  • 如果列位于多个表中(例如,在联接中的两个表中),则语句将失败,并显示“不明确的列”错误。

expr 必须计算为单个值。

RENAME col_name AS col_alias . RENAME (col_name AS col_alias, col_name AS col_alias, ...)

指定应在结果中使用的列别名。

如果您要从多个表中进行选择,请使用 SELECT table_name.* 指定要从特定表中选择所有列,并在 RENAME 中指定非限定列名。例如:

SELECT table_a.* RENAME column_in_table_a AS col_alias_a,
  table_b.* RENAME column_in_table_b AS col_alias_b
  ...
Copy

备注

SELECT * 之后指定关键字组合时:

  • 您不能同时指定 ILIKEEXCLUDE

  • 如果您指定 EXCLUDERENAMEREPLACE

    • 您必须在 RENAMEREPLACE 之前指定 EXCLUDE

      SELECT * EXCLUDE col_a RENAME col_b AS alias_b ...
      
      Copy
      SELECT * EXCLUDE employee_id REPLACE ('DEPT-' || department_id AS department_id) ...
      
      Copy
    • 您不能在 EXCLUDERENAME 中指定同一列。

  • 如果您指定 ILIKERENAMEREPLACE,则必须首先指定 ILIKE

    SELECT * ILIKE '%id%' RENAME department_id AS department ...
    
    Copy
    SELECT * ILIKE '%id%' REPLACE ('DEPT-' || department_id AS department_id) ...
    
    Copy
  • 如果您指定 REPLACERENAME

    • 您必须首先指定 REPLACE

      SELECT * REPLACE ('DEPT-' || department_id AS department_id) RENAME employee_id as employee ...
      
      Copy
    • 您可以在 REPLACERENAME 中指定相同的列名:

      SELECT * REPLACE ('DEPT-' || department_id AS department_id) RENAME department_id as department ...
      
      Copy
col_name

按照 FROM 子句中的定义指定列标识符。

$col_position

按照 FROM 子句中的定义指定列(从 1 开始)的位置。如果从表中引用列,则此数字不能超过表中的最大列数。

expr

指定一个表达式(例如数学表达式),该表达式的计算结果为任何给定行的特定值。

[ AS ] col_alias

指定为生成表达式分配的列别名。此别名用作顶级 SELECT 列表中的显示名称,以及内联视图中的列名称。

不要分配与查询中引用的另一列的名称相同的列别名。例如,如果您选择名为 prod_idproduct_id 的列,请不要将 prod_id 的别名设置为 product_id。请参阅 错误案例:指定与另一个列名称匹配的别名

使用说明

  • 默认情况下,别名和标识符不区分大小写。为保留大小写,请将它们放在双引号 (") 内。有关更多信息,请参阅 对象标识符

  • 如果没有 ORDER BY 子句,则 SELECT 返回的结果是无序集合。对相同的表重复运行相同的查询,这样可能会导致每次都产生不同的输出顺序。如果顺序很重要,请使用 ORDER BY 子句。

  • SELECT 不仅可以用作独立语句,还可以用作其他语句中的子句,例如 INSERT INTO ... SELECT ...;。SELECT 还可以在语句内的 子查询 中使用。

  • 在许多情况下,当您在相同查询的其他部分(采用 JOIN、FROM、WHERE、GROUP BY、其他列表达式等)中对表达式(即 expr AS col_alias)使用列别名时,表达式仅计算一次。

    但是,请注意,在某些情况下,表达式可以计算多次,这可能会导致相同查询的不同部分中使用的别名具有不同的值。

示例

下面提供了几个简单的示例。

文档的其他部分还包含许多其他示例,包括 :doc:`/sql-reference/constructs`的详细说明。

有关查询事件表(其架构由 Snowflake 预定义)的相关示例,请参阅 查看日志消息查看跟踪数据

为示例设置数据

下面的一些查询使用以下表和数据:

CREATE TABLE employee_table (
    employee_ID INTEGER,
    last_name VARCHAR,
    first_name VARCHAR,
    department_ID INTEGER
    );

CREATE TABLE department_table (
    department_ID INTEGER,
    department_name VARCHAR
    );
Copy
INSERT INTO employee_table (employee_ID, last_name, first_name, department_ID) VALUES
    (101, 'Montgomery', 'Pat', 1),
    (102, 'Levine', 'Terry', 2),
    (103, 'Comstock', 'Dana', 2);

INSERT INTO department_table (department_ID, department_name) VALUES
    (1, 'Engineering'),
    (2, 'Customer Support'),
    (3, 'Finance');
Copy

选择所有列 (SELECT *) 的示例

在表中选择所有列

此示例演示如何在 employee_table 中选择所有列:

SELECT * FROM employee_table;
Copy
+-------------+------------+------------+---------------+
| EMPLOYEE_ID | LAST_NAME  | FIRST_NAME | DEPARTMENT_ID |
|-------------+------------+------------+---------------|
|         101 | Montgomery | Pat        |             1 |
|         102 | Levine     | Terry      |             2 |
|         103 | Comstock   | Dana       |             2 |
+-------------+------------+------------+---------------+

选择名称与模式匹配的所有列

此示例演示如何在 employee_table 中选择名称包含 id 的所有列:

SELECT * ILIKE '%id%' FROM employee_table;
Copy
+-------------+---------------+
| EMPLOYEE_ID | DEPARTMENT_ID |
|-------------+---------------|
|         101 |             1 |
|         102 |             2 |
|         103 |             2 |
+-------------+---------------+

选择除一列之外的所有列

此示例演示如何在 employee_table 中选择除 department_id 列之外的所有列:

SELECT * EXCLUDE department_id FROM employee_table;
Copy
+-------------+------------+------------+
| EMPLOYEE_ID | LAST_NAME  | FIRST_NAME |
|-------------+------------+------------|
|         101 | Montgomery | Pat        |
|         102 | Levine     | Terry      |
|         103 | Comstock   | Dana       |
+-------------+------------+------------+

选择除两列或多列之外的所有列

此示例演示如何在 employee_table 中选择除 department_idemployee_id 列之外的所有列:

SELECT * EXCLUDE (department_id, employee_id) FROM employee_table;
Copy
+------------+------------+
| LAST_NAME  | FIRST_NAME |
|------------+------------|
| Montgomery | Pat        |
| Levine     | Terry      |
| Comstock   | Dana       |
+------------+------------+

选择所有列并重命名一列

此示例演示如何在 employee_table 中选择所有列并重命名 department_id 列:

SELECT * RENAME department_id AS department FROM employee_table;
Copy
+-------------+------------+------------+------------+
| EMPLOYEE_ID | LAST_NAME  | FIRST_NAME | DEPARTMENT |
|-------------+------------+------------+------------|
|         101 | Montgomery | Pat        |          1 |
|         102 | Levine     | Terry      |          2 |
|         103 | Comstock   | Dana       |          2 |
+-------------+------------+------------+------------+

选择所有列并重命名多个列

此示例演示如何在 employee_table 中选择所有列并重命名 department_idemployee_id 列:

SELECT * RENAME (department_id AS department, employee_id AS id) FROM employee_table;
Copy
+-----+------------+------------+------------+
|  ID | LAST_NAME  | FIRST_NAME | DEPARTMENT |
|-----+------------+------------+------------|
| 101 | Montgomery | Pat        |          1 |
| 102 | Levine     | Terry      |          2 |
| 103 | Comstock   | Dana       |          2 |
+-----+------------+------------+------------+

选择除一列外的所有列并重命名多个列

此示例演示如何在 employee_table 中选择除 first_name 列之外的所有列,并重命名 department_idemployee_id 列:

SELECT * EXCLUDE first_name RENAME (department_id AS department, employee_id AS id) FROM employee_table;
Copy
+-----+------------+------------+
|  ID | LAST_NAME  | DEPARTMENT |
|-----+------------+------------|
| 101 | Montgomery |          1 |
| 102 | Levine     |          2 |
| 103 | Comstock   |          2 |
+-----+------------+------------+

选择名称与模式匹配的所有列并重命名一列

此示例演示如何在名称包含 idemployee_table 中选择所有列,并重命名 department_id 列:

SELECT * ILIKE '%id%' RENAME department_id AS department FROM employee_table;
Copy
+-------------+------------+
| EMPLOYEE_ID | DEPARTMENT |
|-------------+------------|
|         101 |          1 |
|         102 |          2 |
|         103 |          2 |
+-------------+------------+

选择所有列并替换一列的值

此示例演示如何在 employee_table 中选择所有列,并将 department_id 列中的值替换为前缀为 DEPT- 的 ID:

SELECT * REPLACE ('DEPT-' || department_id AS department_id) FROM employee_table;
Copy
+-------------+------------+------------+---------------+
| EMPLOYEE_ID | LAST_NAME  | FIRST_NAME | DEPARTMENT_ID |
|-------------+------------+------------+---------------|
|         101 | Montgomery | Pat        | DEPT-1        |
|         102 | Levine     | Terry      | DEPT-2        |
|         103 | Comstock   | Dana       | DEPT-2        |
+-------------+------------+------------+---------------+

选择所有列,替换一列的值,然后重命名该列

此示例演示如何在 employee_table 中选择所有列,将 department_id 列中的值替换为前缀为 DEPT- 的 ID,并重命名该列:

SELECT * REPLACE ('DEPT-' || department_id AS department_id) RENAME department_id AS department FROM employee_table;
Copy
+-------------+------------+------------+------------+
| EMPLOYEE_ID | LAST_NAME  | FIRST_NAME | DEPARTMENT |
|-------------+------------+------------+------------|
|         101 | Montgomery | Pat        | DEPT-1     |
|         102 | Levine     | Terry      | DEPT-2     |
|         103 | Comstock   | Dana       | DEPT-2     |
+-------------+------------+------------+------------+

选择名称与模式匹配的所有列,并替换一列的值

此示例演示如何在名称包含 idemployee_table 中选择所有列,并将 DEPT- 追加到 department_id 列中值的前面:

SELECT * ILIKE '%id%' REPLACE('DEPT-' || department_id AS department_id) FROM employee_table;
Copy
+-------------+---------------+
| EMPLOYEE_ID | DEPARTMENT_ID |
|-------------+---------------|
|         101 | DEPT-1        |
|         102 | DEPT-2        |
|         103 | DEPT-2        |
+-------------+---------------+

从多个表中选择所有列,排除一列并重命名该列

此示例联接两个表,从两个表中选择所有列,但排除 employee_table 中一列。该示例还会重命名从 department_table 中选择的一列。

SELECT
  employee_table.* EXCLUDE department_id,
  department_table.* RENAME department_name AS department
FROM employee_table INNER JOIN department_table
  ON employee_table.department_id = department_table.department_id
ORDER BY department, last_name, first_name;
Copy
+-------------+------------+------------+---------------+------------------+
| EMPLOYEE_ID | LAST_NAME  | FIRST_NAME | DEPARTMENT_ID | DEPARTMENT       |
|-------------+------------+------------+---------------+------------------|
|         103 | Comstock   | Dana       |             2 | Customer Support |
|         102 | Levine     | Terry      |             2 | Customer Support |
|         101 | Montgomery | Pat        |             1 | Engineering      |
+-------------+------------+------------+---------------+------------------+

选择特定列 (SELECT colname) 的示例

按名称选择单个列

此示例说明如果您知道员工的 ID,如何查找他们的姓氏。

SELECT last_name FROM employee_table WHERE employee_ID = 101;
+------------+
| LAST_NAME  |
|------------|
| Montgomery |
+------------+
Copy

从联接表中按名称选择多个列

此示例列出每个员工以及每个员工所在部门的名称。输出按部门名称排序,在每个部门中,员工按姓名排序。此查询使用联接将一个表中的信息与另一个表中的信息相关联。

SELECT department_name, last_name, first_name
    FROM employee_table INNER JOIN department_table
        ON employee_table.department_ID = department_table.department_ID
    ORDER BY department_name, last_name, first_name;
+------------------+------------+------------+
| DEPARTMENT_NAME  | LAST_NAME  | FIRST_NAME |
|------------------+------------+------------|
| Customer Support | Comstock   | Dana       |
| Customer Support | Levine     | Terry      |
| Engineering      | Montgomery | Pat        |
+------------------+------------+------------+
Copy

按位置选择列

此示例演示如何使用 $ 按列号(而不是按列名)指定列:

SELECT $2 FROM employee_table ORDER BY $2;
+------------+
| $2         |
|------------|
| Comstock   |
| Levine     |
| Montgomery |
+------------+
Copy

为输出中的列指定别名

此示例说明,输出列不需要直接从 FROM 子句中的表中获取;输出列可以是常规表达式。此示例计算半径为 2.0 的圆的面积。此示例还演示如何使用列别名,以便输出具有有意义的列名称:

SELECT pi() * 2.0 * 2.0 AS area_of_circle;
+----------------+
| AREA_OF_CIRCLE |
|----------------|
|   12.566370614 |
+----------------+
Copy

错误案例:指定与另一个列名称匹配的别名

此示例演示为什么不建议使用与查询中另一列的名称匹配的列别名。此 GROUP BY 查询会导致 SQL 编译器错误,而不是“不明确的列”错误。为 table1product_id 分配的别名 prod_idtable2prod_id 列的名称匹配。此错误的最简单解决方案是为列提供不同的别名。

CREATE OR REPLACE TABLE table1 (product_id NUMBER);

CREATE OR REPLACE TABLE table2 (prod_id NUMBER);

SELECT t1.product_id AS prod_id, t2.prod_id
  FROM table1 AS t1 JOIN table2 AS t2
    ON t1.product_id=t2.prod_id
  GROUP BY prod_id, t2.prod_id;
Copy
001104 (42601): SQL compilation error: error line 1 at position 7
'T1.PRODUCT_ID' in select clause is neither an aggregate nor in the group by clause.
语言: 中文