本文分享的是我自己悟出的从类与对象的角度和用程序设计的思维来理解嵌套查询的一种思路。
文中所用关系实例如下
关系模式、关系与类、对象
首先我们可以把“关系模式”看成是抽象的类,关系的各属性就是类中的成员、属性,而记录就是类的实例。表则是实例的数组。
例如定义表
CREATE TABLE Student (
Sno CHAR(8),
Sname CHAR(10),
Sage INTEGER,
Sclass CHAR(6),
);
用C++来描述就是
class Student{
char Sno[8];
char Sname[10];
int Sage;
char Sclass[6];
};
拥有具体记录的表就相当于数组S[n]。
查询嵌套与函数嵌套
在这种基础上,就可以把查询看成是以循环语句为主体的函数,From规定了循环范围,Where相当于if判断语句,Select则相当于return返回语句。
例如(为代码简洁与书写方便后面都改用Python):
#查询年龄小于18的学生姓名
SELECT
Sname
FROM
Student
WHERE
Sage<18;
就相当于
def f(Student):
result=[]
for s in Student:
if s.Sage<18:
result.append(s.Sname)
return result
这样,就可以将嵌套查询看成嵌套函数了,例如:
#查询选修了课程编号为'001'课的学生姓名
SELECT
Sname
FROM
Student
WHERE
Sno in (
SELECT
Sno
FROM
SC
WHERE
SC.Cno = '001');
用python来写就是:
global SC,Student #表都是全局变量
def f(SC):
result=[]
for sci in SC:
if sci.Cno=='001':
result.append(sci.Sno)
return result
def g(Student):
result=[]
for s in Student:
if s.Sno in f(SC):
result.append(s.Sname)
return result
第一个也可以写成SELECT Sname FROM Student,SC WHERE Student.Sno=SC.Sno AND SC.Cno='001';
所以多表查询可以转成嵌套查询,并且是非相关子查询。
相关子查询与函数局部变量参数
所以用程序设计的函数描述,相关子查询与非相关子查询的区别就在于内函数是否以外函数中的局部变量为参数。上面的例子显然是非相关子查询,下面来举一个相关子查询的例子:
#查询学过编号为'001'的课程的学生名字
SELECT
Sname
FROM
Student Stud
WHERE
Sno in (
SELECT
Sno
FROM
SC
WHERE
Sno = Stud.Sno AND Cno='001');
对应的
global SC,Student
def f(SC,Stud):
result=[]
for sci in SC:
if sci.Sno==Stud.Sno and sci.Cno=='001':
result.append(sci.Sno)
return result
def g(Student):
result=[]
for Stud in Student: #Stud是局部变量
if Stud.Sno in f(SC,Stud):
result.append(Stud.Sname)
return result
以上并不是所有情况都能这样转换,但是可以起到辅助理解的作用
补充
另外,由于python的特性,即列表可以用for循环来构造,上述python代码可以写得更简洁:
SELECT col_name FROM tab_name WHERE condtion;
就对应
[x.col_name for x in tab_name if condition]
返回一个列表,相当于集合
最后一个例子的python语句可以写成:
[Stud.Sname for Stud in Student if Stud.Sno in [s.Sno for s in SC if s.Sno==Stud.Sno and s.Cno=='001']]
虽然有点长但是与SQL语句几乎完全公式化对应