select语句入门

用于查询的语句就一个:
select 列...
from 关系集...
[where 条件...]
[ group by 列... having 条件... ]
[ order by 列 [desc], 列 [desc] ... ]

1.列没什么好讲的,如果在不同关系中同名会ambiguous,要指明所属关系。

2.关系集
--关系集分四种(1) 表(2) 视图(3) 不相关子查询(4) 连接
--关系集可以有多个,用逗号(,)隔开.它的含义是: 这些关系作广义迪卡尔积.也可以这么说:在select语句中,没有主键外键的概念

2.1 专讲连接
因为"在select语句中,没有主键外键的概念",所以例子也不标注
例子
T1(A, B), T2(B, C)

T1
A B
---
a 1
b 2
c 3

T2
B C
---
1 u
2 v
4 w

如果没有join,结果是广义迪卡尔积
select A, T1.B, C
from T1, T2
查询结果
A B C
-----
a 1 u
a 1 v
a 1 w
b 2 u
b 2 v
b 2 w
c 3 v
c 3 u
c 3 w
(1) left outer join
select A, T1.B, C
from T1 left outer join T2 on T1.B=T2.B
查询结果,依照左侧(T1)的B把右侧(T2)的拉过来,如果没有就去空值。
A B C
-----
a 1 u
b 2 v
c 3 (null)

(2) right outer join
select A, T1.B, C
from T1 right outer join T2 on T1.B=T2.B
查询结果,依照右侧(T2)的B把左侧(T1)的拉过来,如果没有就去空值。
A B C
-----
a 1 u
b 2 v
(null) 4 w

(3) inner join
select A, T1.B, C
from T1 inner join T2 on T1.B=T2.B
查询结果,两侧都有的才会取出来
A B C
-----
a 1 u
b 2 v
on 后面的条件可以用等号(等值连接)或者不等号(不等连接).

(4) natural join和内连接选出的关系数目相同 ,但是它自动去找寻两侧相同属性的列,将其做等值连接
select A, T1.B, C
from T1 natural join T2
查询结果,两侧都有的才会取出来
A B C
-----
a 1 u
b 2 v

(5) cross join 类似广义迪卡尔积,取出满足on条件的结果,如果某一方向不全,用null补齐
select A, T1.B, C
from T1 cross join T2 on T1.B=T2.B
查询结果
A B C
-----
a 1 u
b 2 v
c 3 (null)
(null) 4 w

(6) 注意:left outer join, right outer join, cross join 都会产生null的属性值,
如果产生了这种属性值,再此基础上再连接就会出现错误。
比如T1(A, B), T2(B, C), T3(C, D)
select A, T1.B, T2.C, D
from (T1 left outer join T2 on T1.B=T2.B) left outer join T3 on T2.B=T3.B
这句话看似意思是:T1左外连接了T2再去左外连接T3。事实上,这种连接会消灭所有的用null补齐的行(关系)。选择的行数和内连接的相同。

外连接操作是双目运算,一个连接式,要么是一个外连接,要么是一个或多个内连接。外连接出现在连接式中就不允许任何别的连接存在。

3. where
(1) 可与连接转换的条件可等价转换为join的where子句也是连接,如果from子句中有外连接就要注意外连接的唯一性。
select A, T1.B, C
from T1 inner join T2 on T1.B=T2.B
等价于
select A, T1.B, C
from T1 natural join T2
等价于
select A, T1.B, C
from T1, T2 where T1.B=T2.B
如果两个表中还有另外相同的属性列,natural join还会考虑那一列,那时就不等价了。

4. group by 列 having 条件
from子句中的所有关系集(4种,见上面,可以是多个,用逗号分隔)作广义迪卡尔积,为了便于理解,把结果记作R,from子句也可记成from R。
group by 列 是按照这一列的每个属性值把R分成很多groups。比如如果有如下的R
A B C
-----
a 1 u
a 2 v
b 2 v
b 3 w
如果group by A,则分成两个group
group a
B C
---
1 u
2 v

group b
B C
---
2 v
3 w

前面的select和where都针对每个group来进行.但是还有以下两个原则:
(1) 每个组中只能选出一个
(2) select中的'列'必须函数依赖group中的'列'
下面举例说明.
--这样写是错的
select C from R where B=2 group by A
这样写也是错的(等价于上面那个)
select C from R group by A having B=2
因为它违反了第二个原则, 对于一个A不只是有一个C,虽然你可以在每个group中只选出一个.
B=2在where子句中,他和select子句与group子句无关,他不影响原则2.

这样写的是错的
select A from R group by B, C
违反了每一个group只能选一个的原则

这样写是对的
select C from R where B=2 group by A, C
等价于select C from R group by A, C having B=2
这样就做到了select中的'列'[ C ] 必须函数依赖group中的'列'[A, C]

5. order by 子句排序优先级是左到右

**语义说完,下面有两个例子
3张表[*主,F外]
学生表(学号*, 姓名, 所在系, ...)
课程表(课号*, 课名, ...)
选课表(学号F, 课号F, 学期, ...)

1.列出软件系每个同学的姓名,所选课程,成绩。
[分析]选课表和课程表需要一次连接,学生表和他们是一个外连接。但是外连接不能与别的连接共存,所以需要用union,把选课的和没选课的学生列出来。

select 姓名, 课程名, 成绩 from 学生表, 选课表, 课程表
where学生表.学号 = 选课表.学号 and 选课表.课号 = 课程表.课号 and 所在系='软件'
union
select 姓名, '', '' from 学生表 where 学号 not in (select 学号 from 选课表)

''(两个单引号)表示一种空或者0的意思,这样合并之后就满足题目要求了。
2.列出选了所有课程的学生的学号和姓名
[分析]全称量词在SQL语句中不能直接表示,一般课本上都给出用离散数学转化的式子,鉴于太难理解我们可以用group by having解决。having的条件是选择了所有课。

select 学号,姓名 from 选课表group by 学号,姓名 having count(distinct 课号)=(select count(*) from 课程表)

group by中的姓名列是必要的,因为学号列不能决定学号+姓名列,因为select语句没有主键外键的观念,它不知道姓名函数依赖于学号。

上面的查询等价于下面的,我理解不了,抄自课本。
select 学号, 姓名 from 学生表
where not exists (select * from 课程表
where not exists (select * from 选课表
where 课程表.课号=选课表.课号 and 学生表.学号=选课表.学号))
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值