SELECT (Transact-SQL)

适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例 Azure Synapse Analytics 分析平台系统 (PDW) Microsoft Fabric 中的 SQL 分析端点 Microsoft Fabric 中的仓库

从数据库中检索行,并启用从 SQL Server 数据库引擎中的一个或多个表选择一个或多个行或列。 语句的完整语法 SELECT 很复杂,但主要子句可以按如下所示进行汇总:

[ WITH { [ XMLNAMESPACES ] [ common_table_expression ] } ] ]

SELECT select_list [ INTO new_table ]

[ FROM table_source ] [ WHERE search_condition ]

[ GROUP BY group_by_expression ]

[ HAVING search_condition ]

[ WINDOW window_expression ]

[ ORDER BY order_expression [ ASC | DESC ]]

可以在查询之间使用 UNIONEXCEPTINTERSECT 运算符将其结果合并或比较为一个结果集。

Transact-SQL 语法约定

语法

SQL Server 和 Azure SQL 数据库的语法:

<SELECT statement> ::=
    [ WITH { [ XMLNAMESPACES , ] [ <common_table_expression> [ , ...n ] ] } ]
    <query_expression>
    [ ORDER BY <order_by_expression> ]
    [ <FOR Clause> ]
    [ OPTION ( <query_hint> [ , ...n ] ) ]
<query_expression> ::=
    { <query_specification> | ( <query_expression> ) }
    [  { UNION [ ALL ] | EXCEPT | INTERSECT }
        <query_specification> | ( <query_expression> ) [ ...n ] ]
<query_specification> ::=
SELECT [ ALL | DISTINCT ]
    [ TOP ( expression ) [ PERCENT ] [ WITH TIES ] ]
    <select_list>
    [ INTO new_table ]
    [ FROM { <table_source> } [ , ...n ] ]
    [ WHERE <search_condition> ]
    [ <GROUP BY> ]
    [ HAVING <search_condition> ]
[ ; ]

Azure Synapse Analytics、并行数据仓库和 Microsoft Fabric 的语法:

[ WITH <common_table_expression> [ , ...n ] ]
SELECT <select_criteria>
[ ; ]

<select_criteria> ::=
    [ TOP ( top_expression ) ]
    [ ALL | DISTINCT ]
    { * | column_name | expression } [ , ...n ]
    [ FROM { table_source } [ , ...n ] ]
    [ WHERE <search_condition> ]
    [ GROUP BY <group_by_clause> ]
    [ HAVING <search_condition> ]
    [ ORDER BY <order_by_expression> ]
    [ OPTION ( <query_option> [ , ...n ] ) ]

注解

由于语句的复杂性 SELECT ,每个子句都显示详细的语法元素和参数:

语句中 SELECT 子句的顺序非常重要。 可以省略可选子句,但这些子句在使用时必须按适当的顺序出现。

SELECT 仅当这些语句的选择列表包含为函数局部变量赋值的表达式时,才允许在用户定义的函数中使用语句。

使用函数作为服务器名称部件构造 OPENDATASOURCE 的四部分名称可用作表源,无论表名出现在语句中 SELECT 的位置。 无法为Azure SQL 数据库指定四部分名称。

某些语法限制适用于 SELECT 涉及远程表的语句。

SELECT 语句的逻辑处理顺序

以下步骤显示了语句的逻辑处理顺序或绑定顺序 SELECT 。 此顺序确定在一个步骤中定义的对象何时可用于后续步骤中的子句。 例如,如果查询处理器可以绑定到子句中 FROM 定义的表或视图(access),则这些对象及其列可用于所有后续步骤。 相反,由于子 SELECT 句是步骤 8,因此该子句中定义的任何列别名或派生列都不能由前面的子句引用。 但是,后续子句(如 ORDER BY 子句)可以引用它们。 查询处理器确定语句的实际物理执行,顺序可能与此列表不同。

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBEWITH ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP

警告

在某些情况下,以前的序列可能有所不同。 假设视图上有聚集索引,视图排除一些表行,视图的 SELECT 列列表使用将 CONVERT 数据类型从 varchar 更改为 int。在这种情况下, CONVERT 可以在子句执行之前 WHERE 执行。 通常,如果视图很重要,可以修改视图以避免不同的序列。

权限

选择数据需要 SELECT 对表或视图具有权限,该权限可以继承自更高的范围,例如 SELECT 对架构的权限或 CONTROL 表的权限。 或者要求具有 db_datareader 或 db_owner 固定数据库角色或 sysadmin 固定服务器角色的成员身份 。 使用 SELECT INTO 创建新表还需要 CREATE TABLE 权限以及 ALTER SCHEMA 拥有新表的架构的权限。

示例

以下示例使用 AdventureWorksPDW2022 数据库。

A. 使用 SELECT 检索行和列

本部分演示三个代码示例。 第一个代码示例返回表中的所有行(未WHERE指定子句)和所有列(使用*)。DimEmployee

SELECT *
FROM DimEmployee
ORDER BY LastName;

此第二个示例使用表别名实现相同结果。

SELECT e.*
FROM DimEmployee AS e
ORDER BY LastName;

本示例从 AdventureWorksPDW2022 数据库中的表中返回所有行(未WHERE指定子句)和列(FirstNameLastNameStartDateDimEmployee子集。 第三个列标题重命名为 FirstDay

SELECT FirstName,
       LastName,
       StartDate AS FirstDay
FROM DimEmployee
ORDER BY LastName;

本示例仅返回该行的EndDate行,该行DimEmployee不具有该行和一个MMaritalStatus(已NULL婚)。

SELECT FirstName,
       LastName,
       StartDate AS FirstDay
FROM DimEmployee
WHERE EndDate IS NOT NULL
      AND MaritalStatus = 'M'
ORDER BY LastName;

B. 将 SELECT 与列标题和列计算一起使用

下面的示例返回 DimEmployee 表中的所有行,并基于每位员工的 BaseRate 和 40 小时工作周计算他们的总工资。

SELECT FirstName,
       LastName,
       BaseRate,
       BaseRate * 40 AS GrossPay
FROM DimEmployee
ORDER BY LastName;

°C 将 DISTINCT 与 SELECT 一起使用

下面的示例使用 DISTINCTDimEmployee 表中的所有唯一标题生成列表。

SELECT DISTINCT Title
FROM DimEmployee
ORDER BY Title;

D. 使用 Group By

下面的示例查找每天所有销售的总金额。

SELECT OrderDateKey,
       SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
ORDER BY OrderDateKey;

由于使用了 GROUP BY 子句,因此每天只返回一行销售总额。

E. 对多个组使用 GROUP BY

下面的示例查找平均价格和每天的互联网销售总额(按订单日期和促销关键字进行分组)。

SELECT OrderDateKey,
       PromotionKey,
       AVG(SalesAmount) AS AvgSales,
       SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey, PromotionKey
ORDER BY OrderDateKey;

F. 使用 GROUP BY 和 WHERE

下面的示例在只检索订单日期晚于 2002 年 8 月 1 日的行后对结果进行分组。

SELECT OrderDateKey,
       SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
WHERE OrderDateKey > '20020801'
GROUP BY OrderDateKey
ORDER BY OrderDateKey;

G. 将 GROUP BY 与表达式一起使用

以下示例按表达式进行分组。 如果表达式不包含聚合函数,则可以按表达式进行分组。

SELECT SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY (OrderDateKey * 10);

H. 将 GROUP BY 与 ORDER BY 一起使用

下面的示例查找每天的总销售额以及当天的订单。

SELECT OrderDateKey,
       SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
ORDER BY OrderDateKey;

I. 使用 HAVING 子句

此查询使用 HAVING 子句限制结果。

SELECT OrderDateKey,
       SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
HAVING OrderDateKey > 20010000
ORDER BY OrderDateKey;