SQL 语句看上去挺酷,但在数据库内部,它是如何被解释执行的呢?
本文试图用最小的篇幅,解释这个问题.
作者水平有限,内容难免有失偏颇,望请海涵.
首先,一张学生表:
姓名,年龄,班级 = range(3)
张三 = ('张三', 18, '软件一班')
李四 = ('李四', 19, '软件一班')
王五 = ('王五', 19, '软件二班')
学生 = {张三, 李四, 王五}
一张成绩表:
姓名,年龄,班级 = range(3)
张三 = ('张三', 18, '软件一班')
李四 = ('李四', 19, '软件一班')
王五 = ('王五', 19, '软件二班')
学生 = {张三, 李四, 王五}
它在数据库里是这样被执行的:
for x in 学生:
if(x[姓名] == '张三'):
print(x)
解释一下,上面的代码的含义是: 遍历"学生表"找到"姓名"为"张三"的人,并将它打印出来
作为一个新潮的码农,上面的代码,也可以这样写:
结果 = [ s for s in 学生 if s[姓名] == '张三']
print("简单查询结果:",结果)
产生的结果,将是这个样子:
简单查询结果: [('张三', 18, '软件一班')]
前奏完毕,现在进入正题
SQL语句
select 学生.姓名, 成绩.学科, 成绩.分数
from 学生 left join 成绩 on 学生.姓名 = 成绩.姓名
where 学生.姓名 = '张三'
以上的SQL语句是查询"姓名"为"张三"的同学,在成绩表中的"学科"与"成绩"
语意没问题,但关键是How? 计算机该如何去做?
Step one 来个笛卡尔积.
什么是笛卡尔积?
在数学中,两个集合 X 和 Y 的笛卡儿积(Cartesian product),又称直积,
表示为 X × Y,是其第一个对象是 X 的成员而第二个对象是 Y 的一个成员的所有可能的有序对:
具体的说,如果集合 X 是 13 个元素的点数集合 { A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2 }
而集合 Y 是 4 个元素的花色集合 {♠, ♥, ♦, ♣},
则这两个集合的笛卡儿积是 52 个元素的标准扑克牌的集合
{ (A, ♠), (K, ♠), ..., (2, ♠), (A, ♥), ..., (3, ♣), (2, ♣) }。
版权声明,以上引用自wiki。
解释完毕,首先,我们来一个笛卡尔积:
笛卡尔积 = { (x,y) for x in 学生 for y in 成绩}
print("笛卡尔积结果:",sorted(笛卡尔积))#为了显示美观,特意加了一个排序
它的结果是 酱紫的:
笛卡尔积结果:
[(('张三', 18, '软件一班'), ('张三', 'C语言', 70)),
(('张三', 18, '软件一班'), ('张三', '数学', 60)),
(('张三', 18, '软件一班'), ('李四', '数学', 61)),
(('张三', 18, '软件一班'), ('王五', 'C语言', 63)),
(('张三', 18, '软件一班'), ('王五', '数学', 62)),
(('李四', 19, '软件一班'), ('张三', 'C语言', 70)),
(('李四', 19, '软件一班'), ('张三', '数学', 60)),
(('李四', 19, '软件一班'), ('李四', '数学', 61)),
(('李四', 19, '软件一班'), ('王五', 'C语言', 63)),
(('李四', 19, '软件一班'), ('王五', '数学', 62)),
(('王五', 19, '软件二班'), ('张三', 'C语言', 70)),
(('王五', 19, '软件二班'), ('张三', '数学', 60)),
(('王五', 19, '软件二班'), ('李四', '数学', 61)),
(('王五', 19, '软件二班'), ('王五', 'C语言', 63)),
(('王五', 19, '软件二班'), ('王五', '数学', 62))]
数据很多,但绝大多数 没用
接下来,戏法来了,我们在笛卡尔积上加上过滤条件
学生表,成绩表 = range(2)
for x in 笛卡尔积:
if x[学生表][姓名] == x[成绩表][姓名] and x[学生表][姓名] == '张三':
print(x)
新潮的写法是:
最终结果= { (x[学生表][姓名], x[成绩表][学科], x[成绩表][分数]) for x in 笛卡尔积 if x[学生表][姓名] == x[成绩表][姓名] and x[学生表][姓名] == '张三'}
print('结果:', 最终结果)
产生的结果是:
结果:
{('张三', '数学', 60),
('张三', 'C语言', 70)}
正如君亲眼所见,数据库软件处理SQL语句有一定的顺序,首先是from语句,然后blah,blah,blah
what's more?
《SQL Server 2005 技术内幕T—SQL查询》
《Inside Microsoft SQL Server 2005:T-SQL Programminy》抱歉,推荐一本SQL Server的书籍。只看第一章就好。
源代码:
姓名,年龄,班级 = range(3)
张三 = ('张三', 18, '软件一班')
李四 = ('李四', 19, '软件一班')
王五 = ('王五', 19, '软件二班')
学生 = {张三, 李四, 王五}
姓名,学科, 分数 = range(3)
成绩1 = ('张三', '数学', 60)
成绩2 = ('张三', 'C语言', 70)
成绩3 = ('李四', '数学', 61)
成绩4 = ('王五', '数学', 62)
成绩5 = ('王五', 'C语言', 63)
成绩 = {成绩1, 成绩2, 成绩3, 成绩4, 成绩5}
# select 姓名, 年龄, 班级 from 学生 where 姓名 = '张三'
for x in 学生:
if(x[姓名] == '张三'):
print(x)
结果 = [ s for s in 学生 if s[姓名] == '张三']
print("简单查询结果:",结果)
#select 学生.姓名, 成绩.学科, 成绩.分数 from 学生 left join 成绩 on 学生.姓名 = 成绩.姓名 where 学生.姓名 = '张三'
#step one,对两个表做笛卡尔积
笛卡尔积 = { (x,y) for x in 学生 for y in 成绩}
print("笛卡尔积结果:",sorted(笛卡尔积))#为了显示美观,特意加了一个排序
学生表,成绩表 = range(2)
#step two,增加过滤条件
最终结果= { (x[学生表][姓名], x[成绩表][学科], x[成绩表][分数]) for x in 笛卡尔积 if x[学生表][姓名] == x[成绩表][姓名] and x[学生表][姓名] == '张三'}
print('结果:', 最终结果)