十步完全理解 SQL( 四 )


 
7、 SQL 中如同变量的派生表
 
在这之前,我们学习到过 SQL 是一种声明性的语言,并且 SQL 语句中不能包含变量 。但是你能写出类似于变量的语句,这些就叫做派生表:
 
说白了,所谓的派生表就是在括号之中的子查询:
-- A derived tableFROM (SELECT * FROM author)需要注意的是有些时候我们可以给派生表定义一个相关名(即我们所说的别名) 。
-- A derived table with an aliasFROM (SELECT * FROM author) a派生表可以有效的避免由于 SQL 逻辑而产生的问题 。举例来说:如果你想重用一个用 SELECT 和 WHERE 语句查询出的结果,这样写就可以(以 Oracle 为例):

十步完全理解 SQL

文章插图
 
当然了,你也可以给“ a ”创建一个单独的视图,这样你就可以在更广泛的范围内重用这个派生表了 。更多信息可以阅读下面的文章(http://en.wikipedia.org/wiki/View_%28SQL%29) 。
 
我们学到了什么?
 
我们反复强调,大体上来说 SQL 语句就是对表的引用,而并非对字段的引用 。要好好利用这一点,不要害怕使用派生表或者其他更复杂的语句 。
 
8、 SQL 语句中 GROUP BY 是对表的引用进行的操作
 
让我们再回想一下之前的 FROM 语句:
FROM a, b现在,我们将 GROUP BY 应用到上面的语句中:
GROUP BY A.x, A.y, B.z上面语句的结果就是产生出了一个包含三个字段的新的表的引用 。我们来仔细理解一下这句话:当你应用 GROUP BY 的时候,SELECT 后没有使用聚合函数的列,都要出现在 GROUP BY 后面 。(译者注:原文大意为“当你是用 GROUP BY 的时候,你能够对其进行下一级逻辑操作的列会减少,包括在 SELECT 中的列”) 。
 
需要注意的是:其他字段能够使用聚合函数:
SELECT A.x, A.y, SUM(A.z)FROM AGROUP BY A.x, A.y还有一点值得留意的是:MySQL 并不坚持这个标准,这的确是令人很困惑的地方 。(译者注:这并不是说 MySQL 没有 GROUP BY 的功能)但是不要被 MySQL 所迷惑 。GROUP BY 改变了对表引用的方式 。你可以像这样既在 SELECT 中引用某一字段,也在 GROUP BY 中对其进行分组 。
 
我们学到了什么?
 
GROUP BY,再次强调一次,是在表的引用上进行了操作,将其转换为一种新的引用方式 。
 
9、 SQL 语句中的 SELECT 实质上是对关系的映射
 
我个人比较喜欢“映射”这个词,尤其是把它用在关系代数上 。(译者注:原文用词为 projection,该词有两层含义,第一种含义是预测、规划、设计,第二种意思是投射、映射,经过反复推敲,我觉得这里用映射能够更直观的表达出 SELECT 的作用) 。一旦你建立起来了表的引用,经过修改、变形,你能够一步一步的将其映射到另一个模型中 。SELECT 语句就像一个“投影仪”,我们可以将其理解成一个将源表中的数据按照一定的逻辑转换成目标表数据的函数 。
 
通过 SELECT语句,你能对每一个字段进行操作,通过复杂的表达式生成所需要的数据 。
 
SELECT 语句有很多特殊的规则,至少你应该熟悉以下几条:
 
  1. 你仅能够使用那些能通过表引用而得来的字段;
  2. 如果你有 GROUP BY 语句,你只能够使用 GROUP BY 语句后面的字段或者聚合函数;
  3. 当你的语句中没有 GROUP BY 的时候,可以使用开窗函数代替聚合函数;
  4. 当你的语句中没有 GROUP BY 的时候,你不能同时使用聚合函数和其它函数;
  5. 有一些方法可以将普通函数封装在聚合函数中;
  6. ……
 
一些更复杂的规则多到足够写出另一篇文章了 。比如:为何你不能在一个没有 GROUP BY 的 SELECT 语句中同时使用普通函数和聚合函数?(上面的第 4 条)
 
原因如下: