7、 SQL 中如同变量的派生表
在这之前,我们学习到过 SQL 是一种声明性的语言,并且 SQL 语句中不能包含变量 。但是你能写出类似于变量的语句,这些就叫做派生表:
说白了,所谓的派生表就是在括号之中的子查询:
-- A derived tableFROM (SELECT * FROM author)
需要注意的是有些时候我们可以给派生表定义一个相关名(即我们所说的别名) 。
-- A derived table with an aliasFROM (SELECT * FROM author) a
派生表可以有效的避免由于 SQL 逻辑而产生的问题 。举例来说:如果你想重用一个用 SELECT 和 WHERE 语句查询出的结果,这样写就可以(以 Oracle 为例):
文章插图
当然了,你也可以给“ 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 语句有很多特殊的规则,至少你应该熟悉以下几条:
- 你仅能够使用那些能通过表引用而得来的字段;
- 如果你有 GROUP BY 语句,你只能够使用 GROUP BY 语句后面的字段或者聚合函数;
- 当你的语句中没有 GROUP BY 的时候,可以使用开窗函数代替聚合函数;
- 当你的语句中没有 GROUP BY 的时候,你不能同时使用聚合函数和其它函数;
- 有一些方法可以将普通函数封装在聚合函数中;
- ……
一些更复杂的规则多到足够写出另一篇文章了 。比如:为何你不能在一个没有 GROUP BY 的 SELECT 语句中同时使用普通函数和聚合函数?(上面的第 4 条)
原因如下:
- 凭直觉,这种做法从逻辑上就讲不通 。
- 如果直觉不能够说服你,那么语法肯定能 。SQL : 1999 标准引入了 GROUPING SETS,SQL:2003 标准引入了 group sets : GROUP BY()。无论什么时候,只要你的语句中出现了聚合函数,而且并没有明确的 GROUP BY 语句,这时一个不明确的、空的 GROUPING SET 就会被应用到这段 SQL 中 。因此,原始的逻辑顺序的规则就被打破了,映射(即 SELECT )关系首先会影响到逻辑关系,其次就是语法关系 。(译者注:这段话原文就比较艰涩,可以简单理解如下:在既有聚合函数又有普通函数的 SQL 语句中,如果没有 GROUP BY 进行分组,SQL 语句默认视整张表为一个分组,当聚合函数对某一字段进行聚合统计的时候,引用的表中的每一条 record 就失去了意义,全部的数据都聚合为一个统计值,你此时对每一条 record 使用其它函数是没有意义的) 。
推荐阅读
- Paxos算法为什么说是Raft,Zab协议的鼻祖,及原理解析
- 深入理解Linux IO复用之epoll
- 看都不懂的三层架构,到底要怎么理解?
- 共识算法Raft为什么这么流行,及原理解析
- 活死人意思 活死人的理解
- 看母树大红袍 加深理解武夷山茶文化
- 理解Spring:IOC的原理及手动实现
- PHP中钩子的理解与实例教程
- 这几点行为完全不会伤车,8成车主却坚信不疑,不懂的快来看看
- Linux 虚拟内存和物理内存的理解