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>, ... )
}
]
您可以在 SELECT * 之后指定以下关键字组合。关键字必须按如下所示的顺序排列:
SELECT * ILIKE ... REPLACE ...
SELECT * ILIKE ... RENAME ...
SELECT * ILIKE ... REPLACE ... RENAME ...
SELECT * EXCLUDE ... REPLACE ...
SELECT * EXCLUDE ... RENAME ...
SELECT * EXCLUDE ... REPLACE ... RENAME ...
SELECT * REPLACE ... RENAME ...
选择特定列¶
[ ... ]
SELECT [ { ALL | DISTINCT } ]
[ TOP <n> ]
{
[{<object_name>|<alias>}.]<col_name>
| [{<object_name>|<alias>}.]$<col_position>
| <expr>
}
[ [ AS ] <col_alias> ]
[ , ... ]
[ ... ]
列的列表支持尾随逗号。例如,支持以下 SELECT 语句:
SELECT emp_id,
name,
dept,
FROM employees;
有关 SELECT 语句和语句内其他子句的更多信息,请参阅 查询语法。
参数¶
ALL | DISTINCT
指定是否对结果集执行重复消除:
ALL
包括结果集中的所有值。DISTINCT
消除结果集中的重复值。
默认:
ALL
TOP n
指定要返回的最大结果数。请参阅 TOP <n>。
object_name
或 .alias
按照 FROM 子句中定义,指定对象标识符或对象别名。
*
星号是简写,指明输出应包括指定对象的所有列,或者所有对象的所有列(如果
*
未使用对象名称或别名限定)。在对象上执行 DESCRIBE 命令后,这些列会按显示的顺序返回。指定
*
时,您还可以指定ILIKE
、EXCLUDE
、REPLACE
和RENAME
: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 ...
REPLACE (expr AS col_name [ , expr AS col_name, ...] )
将
col_name
的值替换为计算表达式的expr
值。例如,要在
'DEPT-'
列中的值前面追加字符串department_id
,请使用:SELECT * REPLACE ('DEPT-' || department_id AS department_id) ...
对于
col_name
:该列必须存在,并且不能由
ILIKE
或EXCEPT
筛选掉。您不能在替换列表中多次指定同一列。
如果列位于多个表中(例如,在联接中的两个表中),则语句将失败,并显示“不明确的列”错误。
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 ...
备注
在
SELECT *
之后指定关键字组合时:您不能同时指定
ILIKE
和EXCLUDE
。如果您指定
EXCLUDE
与RENAME
或REPLACE
:您必须在
RENAME
和REPLACE
之前指定EXCLUDE
:SELECT * EXCLUDE col_a RENAME col_b AS alias_b ...
SELECT * EXCLUDE employee_id REPLACE ('DEPT-' || department_id AS department_id) ...
您不能在
EXCLUDE
和RENAME
中指定同一列。
如果您指定
ILIKE
与RENAME
或REPLACE
,则必须首先指定ILIKE
:SELECT * ILIKE '%id%' RENAME department_id AS department ...
SELECT * ILIKE '%id%' REPLACE ('DEPT-' || department_id AS department_id) ...
如果您指定
REPLACE
和RENAME
:您必须首先指定
REPLACE
:SELECT * REPLACE ('DEPT-' || department_id AS department_id) RENAME employee_id as employee ...
您可以在
REPLACE
和RENAME
中指定相同的列名:SELECT * REPLACE ('DEPT-' || department_id AS department_id) RENAME department_id as department ...
col_name
按照 FROM 子句中的定义指定列标识符。
$col_position
按照 FROM 子句中的定义指定列(从 1 开始)的位置。如果从表中引用列,则此数字不能超过表中的最大列数。
expr
指定一个表达式(例如数学表达式),该表达式的计算结果为任何给定行的特定值。
[ AS ] col_alias
指定为生成表达式分配的列别名。此别名用作顶级 SELECT 列表中的显示名称,以及内联视图中的列名称。
不要分配与查询中引用的另一列的名称相同的列别名。例如,如果您选择名为
prod_id
和product_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 );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');
选择所有列 (SELECT *) 的示例¶
在表中选择所有列¶
此示例演示如何在 employee_table
中选择所有列:
SELECT * FROM employee_table;
+-------------+------------+------------+---------------+
| 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;
+-------------+---------------+
| EMPLOYEE_ID | DEPARTMENT_ID |
|-------------+---------------|
| 101 | 1 |
| 102 | 2 |
| 103 | 2 |
+-------------+---------------+
选择除一列之外的所有列¶
此示例演示如何在 employee_table
中选择除 department_id
列之外的所有列:
SELECT * EXCLUDE department_id FROM employee_table;
+-------------+------------+------------+
| EMPLOYEE_ID | LAST_NAME | FIRST_NAME |
|-------------+------------+------------|
| 101 | Montgomery | Pat |
| 102 | Levine | Terry |
| 103 | Comstock | Dana |
+-------------+------------+------------+
选择除两列或多列之外的所有列¶
此示例演示如何在 employee_table
中选择除 department_id
和 employee_id
列之外的所有列:
SELECT * EXCLUDE (department_id, employee_id) FROM employee_table;
+------------+------------+
| LAST_NAME | FIRST_NAME |
|------------+------------|
| Montgomery | Pat |
| Levine | Terry |
| Comstock | Dana |
+------------+------------+
选择所有列并重命名一列¶
此示例演示如何在 employee_table
中选择所有列并重命名 department_id
列:
SELECT * RENAME department_id AS department FROM employee_table;
+-------------+------------+------------+------------+
| EMPLOYEE_ID | LAST_NAME | FIRST_NAME | DEPARTMENT |
|-------------+------------+------------+------------|
| 101 | Montgomery | Pat | 1 |
| 102 | Levine | Terry | 2 |
| 103 | Comstock | Dana | 2 |
+-------------+------------+------------+------------+
选择所有列并重命名多个列¶
此示例演示如何在 employee_table
中选择所有列并重命名 department_id
和 employee_id
列:
SELECT * RENAME (department_id AS department, employee_id AS id) FROM employee_table;
+-----+------------+------------+------------+
| ID | LAST_NAME | FIRST_NAME | DEPARTMENT |
|-----+------------+------------+------------|
| 101 | Montgomery | Pat | 1 |
| 102 | Levine | Terry | 2 |
| 103 | Comstock | Dana | 2 |
+-----+------------+------------+------------+
选择除一列外的所有列并重命名多个列¶
此示例演示如何在 employee_table
中选择除 first_name
列之外的所有列,并重命名 department_id
和 employee_id
列:
SELECT * EXCLUDE first_name RENAME (department_id AS department, employee_id AS id) FROM employee_table;
+-----+------------+------------+
| ID | LAST_NAME | DEPARTMENT |
|-----+------------+------------|
| 101 | Montgomery | 1 |
| 102 | Levine | 2 |
| 103 | Comstock | 2 |
+-----+------------+------------+
选择名称与模式匹配的所有列并重命名一列¶
此示例演示如何在名称包含 id
的 employee_table
中选择所有列,并重命名 department_id
列:
SELECT * ILIKE '%id%' RENAME department_id AS department FROM employee_table;
+-------------+------------+
| 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;
+-------------+------------+------------+---------------+
| 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;
+-------------+------------+------------+------------+
| EMPLOYEE_ID | LAST_NAME | FIRST_NAME | DEPARTMENT |
|-------------+------------+------------+------------|
| 101 | Montgomery | Pat | DEPT-1 |
| 102 | Levine | Terry | DEPT-2 |
| 103 | Comstock | Dana | DEPT-2 |
+-------------+------------+------------+------------+
选择名称与模式匹配的所有列,并替换一列的值¶
此示例演示如何在名称包含 id
的 employee_table
中选择所有列,并将 DEPT-
追加到 department_id
列中值的前面:
SELECT * ILIKE '%id%' REPLACE('DEPT-' || department_id AS department_id) FROM employee_table;
+-------------+---------------+
| 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;
+-------------+------------+------------+---------------+------------------+
| 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 |
+------------+
从联接表中按名称选择多个列¶
此示例列出每个员工以及每个员工所在部门的名称。输出按部门名称排序,在每个部门中,员工按姓名排序。此查询使用联接将一个表中的信息与另一个表中的信息相关联。
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 |
+------------------+------------+------------+
按位置选择列¶
此示例演示如何使用 $
按列号(而不是按列名)指定列:
SELECT $2 FROM employee_table ORDER BY $2;
+------------+
| $2 |
|------------|
| Comstock |
| Levine |
| Montgomery |
+------------+
为输出中的列指定别名¶
此示例说明,输出列不需要直接从 FROM
子句中的表中获取;输出列可以是常规表达式。此示例计算半径为 2.0 的圆的面积。此示例还演示如何使用列别名,以便输出具有有意义的列名称:
SELECT pi() * 2.0 * 2.0 AS area_of_circle;
+----------------+
| AREA_OF_CIRCLE |
|----------------|
| 12.566370614 |
+----------------+
错误案例:指定与另一个列名称匹配的别名¶
此示例演示为什么不建议使用与查询中另一列的名称匹配的列别名。此 GROUP BY 查询会导致 SQL 编译器错误,而不是“不明确的列”错误。为 table1
中 product_id
分配的别名 prod_id
与 table2
中 prod_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;
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.