Select语句
进园一年多了,看了无数别人的博客,自己从未贡献过,不是自私,是不敢。以前都是记到自己的QQ空间,不敢用自己的烂文污染博客园,今天是首发(没有复制粘贴,全是原创),不对的地方欢迎拍砖指出!
都说Select语句是SQL语言的灵魂,这也难怪我断断续续研究它两三次了,时间跨度也有两年,到现在都不敢说完全懂了它。
先看看Select语句的基本语法格式吧(SQL Server平台下):
SELECT [TOP n | TOP n PERCENT] <字段列表>
[INTO 新表名]
FROM <表名(包括派生表)/视图名列表>
[WHERE 条件表达式]
[GROUP BY 列名列表]
[HAVING 条件表达式]
[ORDER BY 列名1 [ASC|DESC],列名2 [ASC|DESC],...,列名n [ASC|DESC]]
[COMPUTE 行集合函数名(统计表达式) [,...n] [BY 分类表达式] [,...n]]
说明:
[ ]:表示可选语法项。
< >:表示实际的语句中要用相应的内容替代。
[,...n]:表示前面的内容可以重复多次。
各子句的详细用法就不多说了,其实,我一直以来被这个 Select 语句所迷惑的地方是它的各个子句的执行顺序问题。搞了好久,现在总算是清晰了很多。
现在总结一下,其实 Select 语句的真实执行顺序(大量实验后总结所得)如下:
1、From 子句组装来自不同数据源(包括基本表、派生表、视图等等)的数据,返回初始结果集。
2、Where 子句根据条件对初始结果集中的记录进行筛选,返回新的结果集。
3、Group by 子句将上一步中的结果集按指定的列或列组合进行分组。
4、Having 子句筛选出符合条件的分组。
5、Order by 子句对结果集进行排序。
6、Select 子句对结果集进行投影选出需要的列,同时计算 select 子句下的所有表达式并执行集合函数。
7、Top 子句返回投影后的结果集最前面的 n 或者 n% 行。
8、Compute [By] 子句对最后的结果集按By后面给出的列进行分组显示,并按指定列对分组进行小计(如果没有By,则直接对结果集按指定列进行小计)。
8、用 Into 子句将查询结果保存到一个新表中。(这里有两个步骤8,因为这两个子句是并列为最后一步的,只能选择其中之一,或者两者都不选)
注意:
一、Into 子句不能和 Compute [By] 子句同时使用。
二、如果使用了 Group by 子句,则 Select 子句只能投影属于 Group by 子句中的列或者其他被集合函数包含了的列(这是因为使用Group by子句进行分组时,会产生新的临时结果集,并与分组前的结果集形成对应关系,这个新的临时结果集只包含用于分组的列或列组合,后面的Select子句就是对这个新的临时结果集进行投影的。但Select子句还可以通过集合函数,并利用新的临时结果集与分组前的结果集形成的对应关系,将经过聚合的其他列也投影出来)。
三、如果使用了 Group by 子句,Order by 子句只能用属于 Group by 子句中的列或者其他被集合函数包含了的列进行排序。
四、如果使用了 Compute by 子名,则必须使用 Order by 子句。并且Compute by子句只能用出现在 Order by 子句中的表达式(可以是其子集)进行分组和小计,而且必须按相同的序列使用。
五、Compute by 子句后面的表达式必须是出现在Select子句中的表达式,而且必须是完全一样的表达式,不允许使用别名。(这是因为Compute by 子句是对已经成型的最终结果集做分组小计的。)
六、Group by、Order by、Compute by等子句不能使用数据类型是text、ntext 或 image 的列。
七、特别要指出的一点是:当使用Union进行联合查询时,最后一个Select查询后跟的 Order by 子句不属于Union前后的任何一个Select查询,这个 order by 是针对整个 Union 后的结果集的,所以这个order by子句用于排序的列也必须是结果集中的列(即第一个select查询中所选择的列)。
另外,Select语句中除了Select子句和From子句在绝大多数情况下都是必选语法项外,其他子句都是可选语法项,但整体执行顺序不会变。
Select语句集合了关系数据库的所有关系运算,包括传统的集合运算(并、差、交和广义笛卡尔积)以及专门的关系运算(选择运算、投影运算、连接运算和除运算),这也是它使用频率最高,成为SQL语言的灵魂的原因。
先看看Select语句的基本语法格式吧(SQL Server平台下):
SELECT [TOP n | TOP n PERCENT] <字段列表>
[INTO 新表名]
FROM <表名(包括派生表)/视图名列表>
[WHERE 条件表达式]
[GROUP BY 列名列表]
[HAVING 条件表达式]
[ORDER BY 列名1 [ASC|DESC],列名2 [ASC|DESC],...,列名n [ASC|DESC]]
[COMPUTE 行集合函数名(统计表达式) [,...n] [BY 分类表达式] [,...n]]
说明:
[ ]:表示可选语法项。
< >:表示实际的语句中要用相应的内容替代。
[,...n]:表示前面的内容可以重复多次。
各子句的详细用法就不多说了,其实,我一直以来被这个 Select 语句所迷惑的地方是它的各个子句的执行顺序问题。搞了好久,现在总算是清晰了很多。
现在总结一下,其实 Select 语句的真实执行顺序(大量实验后总结所得)如下:
1、From 子句组装来自不同数据源(包括基本表、派生表、视图等等)的数据,返回初始结果集。
2、Where 子句根据条件对初始结果集中的记录进行筛选,返回新的结果集。
3、Group by 子句将上一步中的结果集按指定的列或列组合进行分组。
4、Having 子句筛选出符合条件的分组。
5、Order by 子句对结果集进行排序。
6、Select 子句对结果集进行投影选出需要的列,同时计算 select 子句下的所有表达式并执行集合函数。
7、Top 子句返回投影后的结果集最前面的 n 或者 n% 行。
8、Compute [By] 子句对最后的结果集按By后面给出的列进行分组显示,并按指定列对分组进行小计(如果没有By,则直接对结果集按指定列进行小计)。
8、用 Into 子句将查询结果保存到一个新表中。(这里有两个步骤8,因为这两个子句是并列为最后一步的,只能选择其中之一,或者两者都不选)
注意:
一、Into 子句不能和 Compute [By] 子句同时使用。
二、如果使用了 Group by 子句,则 Select 子句只能投影属于 Group by 子句中的列或者其他被集合函数包含了的列(这是因为使用Group by子句进行分组时,会产生新的临时结果集,并与分组前的结果集形成对应关系,这个新的临时结果集只包含用于分组的列或列组合,后面的Select子句就是对这个新的临时结果集进行投影的。但Select子句还可以通过集合函数,并利用新的临时结果集与分组前的结果集形成的对应关系,将经过聚合的其他列也投影出来)。
三、如果使用了 Group by 子句,Order by 子句只能用属于 Group by 子句中的列或者其他被集合函数包含了的列进行排序。
四、如果使用了 Compute by 子名,则必须使用 Order by 子句。并且Compute by子句只能用出现在 Order by 子句中的表达式(可以是其子集)进行分组和小计,而且必须按相同的序列使用。
五、Compute by 子句后面的表达式必须是出现在Select子句中的表达式,而且必须是完全一样的表达式,不允许使用别名。(这是因为Compute by 子句是对已经成型的最终结果集做分组小计的。)
六、Group by、Order by、Compute by等子句不能使用数据类型是text、ntext 或 image 的列。
七、特别要指出的一点是:当使用Union进行联合查询时,最后一个Select查询后跟的 Order by 子句不属于Union前后的任何一个Select查询,这个 order by 是针对整个 Union 后的结果集的,所以这个order by子句用于排序的列也必须是结果集中的列(即第一个select查询中所选择的列)。
另外,Select语句中除了Select子句和From子句在绝大多数情况下都是必选语法项外,其他子句都是可选语法项,但整体执行顺序不会变。
Select语句集合了关系数据库的所有关系运算,包括传统的集合运算(并、差、交和广义笛卡尔积)以及专门的关系运算(选择运算、投影运算、连接运算和除运算),这也是它使用频率最高,成为SQL语言的灵魂的原因。