上关系图
今天详细谈谈select(简单篇)
一、结构
select | 要投影的列 | (可以出现聚合函数) |
from | 表 或 视图 | |
[where | 选择的条件] | |
[group by | 按照其分组的列 | (该列相同只为一组) |
[having | 小组筛选条件]] | (可以出现聚合函数,作用于小组) |
[order by | 按照其排序的列 | [ASC|DESC]] |
(这里空白不知道怎么删)
二、多种用法
1、单表查询(满足条件开始才是重点)
我们初学者一般就会单表查询,就是根据条件查看表中信息,其关键就是在于where条件筛选
先简单建个表
create table Persons(
id number,
name varchar,
sex char,
age number,
city varchar
);
这里把所有情况列举出来
--查询指定列
select id,name form Persons;
--查全部
select * from Persons;
--查经过计算后的值
select sex,count(1)
from Persons
group by sex;
--消重复
select distinct sex,city --distinct对两个字段都进行了消重
from Persons;
--满足条件where
重点在于找满足条件的语句,先来总结一下查询条件——谓词
确定范围(比较运算) | =、 >、 >=、<、 <=、 <>(有些能用!=)、 between and |
确定集合 | in |
字符匹配 | like |
空值 | is null、 is not null( not is null) |
多重条件(逻辑运算) | and、 or、 not |
(1)确定范围
--确定范围(找广州适婚人士)
select * from Persons
where city='广州'
and (
(sex='女' and age>=20)
or(sex='男' and age>=22)
);
(2)确定集合
--确定集合(找在广州或北京的成年人)
select * from Persons
where city in ('广州','北京')
and age >= 18;
(3)字符匹配
学习C++、python或java的同学有学到正则表达式吗?这个差不多
列名 like <匹配串> | (以下是匹配串的形式) |
_ | 匹配一个字符 |
% | 匹配任意个字符 |
[] | 匹配[]中任意字符 |
[^] | 不匹配[]中任意字符 |
不会的同学来看这里,会的跳过分割线
'_',可以匹配1、王、#,不能匹配12、小张(_可以替代一个字符)
同理'%'可以替代任意多个字符
‘[张]%’,可以匹配张新成、张益达、张郎,
而'[张王]%',可以匹配以上张姓,还可以匹配王姓,也就是张开头或王开头都可以([]中的字符相互为或的关系)
练习:‘[520]_’能匹配出'520'吗?
'[^张王]_',可以匹配伊一、李娜,不能匹配以上张姓、王姓(有^的[]中的字符都要排除再匹配)
--查湖北或湖南的人大于2的人数
select sex,count(city)
from Persons
where city like '湖%'
group by sex
having count(*)>=2;
(4)空值
不赋值默认为空值null,除非你为该字段设置了默认值default,或者你设置了unique、primary key、not null,这些后续会说
(5)多重条件
前面写语句一直在用啊
2、连接查询
上面的内容是不是一下子就让整篇低级了,先别急接下来还是低级内容
含义:就是有时候要查的内容在这个表上但是你要筛选的条件在另一个表上
先来建另一个表
create table SC(
id number,
class_id number,
class_name varchar,
class_type varchar
);
内连接查询(自然连接) | 最常用 |
外连接查询 | 包括找不到匹配项的连接 |
自连接查询 | 表自身的连接 |
复合条件连接查询 |
连接的内容麻烦了,需要用图来说明
笛卡尔积(2*3 连接 3*2 -> 5*6)
等值连接
字段2若两属性相同则选择该行
(1)内连接(自然连接)
在等值连接的基础上去掉重复的2字段
以上表有共同属性2(或不同属性但同值),通过2将它们连接
--1(常用)
select * from Persons,SC
where Persons.id=SC.id
and age >= 18;
--2
select *
from Persons join SC
on Persons.id=SC.id
and age >= 18;
(2)外连接
在自然连接的基础上,保留了未被选中的项
左外连接仅保留上图table 3前三行,右外连接仅保留上图table 3中1、2、4行。
--全外连接(两个表都完整保留)
select *
from Persons full join SC
on Persons.id=SC.id
and age >= 18;
--左外连接(Persons表完整保留)
select * from Persons,SC
where Persons.id=SC.id(+)
and age >= 18;
--右外连接(SC表完整保留)
select * from Persons,SC
where Persons.id(+)=SC.id
and age >= 18;
--(更推荐这种写法,符合外连接的定义)
select *
from Persons right join SC
on Persons.id=SC.id
and age >= 18;
--去运行一下这几段就知道为什么这么说了
(3)自身连接
加点东西,给他们加上小组长号group_num
alter table Persons add(group_num number(10));
通过将每一行id与每一行group_num进行匹配找出结果
select p1.name,p2.name
from Persons p1,Persons p2
where p1.id=p2.group_num
order by p1.id;
3、嵌套查询
就是在查询语句中再插一个查询语句
带有IN谓词 | 父查询 in(子查询) |
带有比较运算符 | 父查询 比较(子查询) |
带有ANY或ALL谓词 | 父 比较 any或all(子) |
(1)in谓词
--(1)、in
--求总分大于等于80的学生
select distinct name,city --连接
from Persons p,sc_score s
where p.id=s.id
and total_s >= 80;
select distinct name,city --嵌套
from Persons
where id in(
select id
from sc_score
where total_s >= 80);
结果:
(2)比较运算符
由于where之后不能使用聚合函数,可嵌套求解
--(2)、比较
--求总分大于等于平均分的学生
select name,total_s
from Persons p,sc_score s
where p.id=s.id
and total_s >= (
select avg(total_s)
from sc_score);
结果:
(3)any和all
any,任一元素,至少一个
all,任意元素,全部
--(3)1、any
--求总分大于(任一广州同学总分)的同学
select name,total_s,city
from Persons p,sc_score s
where p.id=s.id
and total_s >= any(
select total_s
from sc_score,Persons
where city = '广州');
结果:
--(3)2、all
--求总分大于(所有广州同学总分)的同学
select name,total_s,city
from Persons p,sc_score s
where p.id=s.id
and total_s >= all(
select total_s
from sc_score,Persons
where city = '广州');
结果:
(不愧是河北的同学!)
4、带有exists谓词的相关子查询
父查询 exists(子查询),判断子查询对于父查询结果是否为真
还有not exists,就是反义,不多讲。exists和in谓词有些类似,但子查询不返回实际数据,只返回逻辑值‘true’或‘false’
-- exists
--求总分大于等于80的同学
select distinct name,city --连接
from Persons p,sc_score s
where total_s >= 80
and p.id=s.id;
select name,city --in谓词
from Persons
where id in(
select id from sc_score s
where total_s >= 80);
select name,city --exists子查询
from Persons p
where exists(
select * from sc_score s
where p.id=s.id
and total_s >= 80);
结果:
总结:exists意义有点像if中的条件
5、集合查询
union(去重),union all(不去重)并集,intersect交集,minus差集
--union(去重,排序)
select name,city from Persons
where city in ('广州','北京')
union
select name,city from Persons
where city in ('湖北','北京');
--union all(不去重,不排序)
select name,city from Persons
where city in ('广州','北京')
union all
select name,city from Persons
where city in ('湖北','北京');
--intersect(取重复)
select name,city from Persons
where city in ('广州','北京')
intersect
select name,city from Persons
where city in ('湖北','北京');
--minus(减掉重复)
select name,city from Persons
where city in ('广州','北京')
minus
select name,city from Persons
where city in ('湖北','北京');
结果:
union
union all
intersect
minus
完