《Oracle(二)- 查询》

一、单表查询

(一)简单条件查询

1.精确查询

需求:查询水表编号为 30408 的业主记录

查询语句:

select * from T_OWNERS where watermeter='30408'

查询结果:

2.模糊查询

需求:查询业主名称包含“刘”的业主记录

查询语句:

select * from t_owners where name like '%刘%'

查询结果:

3. and 运算符

需求:查询业主名称包含“刘”的并且门牌号包含 5 的业主记录

查询语句:

select * from t_owners where name like '%刘%' and housenumber like '%5%'

查询结果:

4. or 运算符

需求:查询业主名称包含“刘”的或者门牌号包含 5 的业主记录

查询语句:

select * from t_owners where name like '%刘%' or housenumber like '%5%'

查询结果:

5. and 与 or 运算符混合使用

需求:查询业主名称包含“刘”的或者门牌号包含 5 的业主记录,并且地址编号 为 3 的记录。

查询语句:

select * from t_owners where (name like '%刘%' or housenumber
like '%5%') and addressid=3

查询结果:

因为 and 的优先级比 or 大,所以我们需要用 ( ) 来改变优先级。

6. 范围查询

需求:查询台账记录中用水字数大于等于 10000,并且小于等于 20000 的记录

我们可以用>= 和<=来实现,查询语句:

select * from T_ACCOUNT where usenum>=10000 and usenum<=20000

我们也可以用 between … and …来实现,查询语句:

select * from T_ACCOUNT where usenum between 10000 and 20000

7. 空值查询

需求:查询 T_PRICETABLE 表中 MAXNUM 为空的记录

查询语句:

select * from T_PRICETABLE t where maxnum is null

查询结果:

需求:查询 T_PRICETABLE 表中 MAXNUM 不为空的记录

查询语句:

select * from T_PRICETABLE t where maxnum is not null

查询结果:

(二)去掉重复记录

需求:查询业主表中的地址 ID,不重复显示

查询语句:

select distinct addressid from T_OWNERS

查询结果:

(三)排序查询

1.升序排序

需求:对 T_ACCOUNT 表按使用量进行升序排序

查询语句:

select * from T_ACCOUNT order by usenum

查询结果:

2.降序排序

需求:对 T_ACCOUNT 表按使用量进行降序排序

查询语句:

select * from T_ACCOUNT order by usenum desc

查询结果:

(四)基于伪列的查询

在 Oracle 的表的使用过程中,实际表中还有一些附加的列,称为伪列。伪列就
像表中的列一样,但是在表中并不存储。伪列只能查询,不能进行增删改操作。
接下来学习两个伪列:ROWID 和 ROWNUM。

1 ROWID

表中的每一行在数据文件中都有一个物理地址,ROWID 伪列返回的就是该行的
物理地址。使用 ROWID 可以快速的定位表中的某一行。ROWID 值可以唯一的
标识表中的一行。由于 ROWID 返回的是该行的物理地址,因此使用 ROWID 可
以显示行是如何存储的。

查询语句:

select rowID,t.* from T_AREA t

查询结果:

我们可以通过指定 ROWID 来查询记录

查询语句:

select rowID,t.*
from T_AREA t
where ROWID='AAAM1uAAGAAAAD8AAC';

查询结果:

2 ROWNUM

在查询的结果集中,ROWNUM 为结果集中每一行标识一个行号,第一行返回 1, 第二行返回 2,以此类推。通过 ROWNUM 伪列可以限制查询结果集中返回的行数。

查询语句:

select rownum,t.* from T_OWNERTYPE t

查询结果:

我们的分页查询需要用到此伪列,在本章第四小节详细讲解。

(五)聚合统计

ORACLE 的聚合统计是通过分组函数来实现的,与 MYSQL 一致。

1. 聚合函数

(1)求和 sum

需求:统计 2012 年所有用户的用水量总和

查询语句:

select sum(usenum) from t_account where year='2012'

查询结果:

(2)求平均 avg

需求:统计 2012 年所有用水量(字数)的平均值

查询语句:

select avg(usenum) from T_ACCOUNT where year='2012'

查询结果:

(3)求最大值 max

需求:统计 2012 年最高用水量(字数)

查询语句:

select max(usenum) from T_ACCOUNT where year='2012'

查询结果:

(4)求最小值 min

需求:统计 2012 年最低用水量(字数)

查询语句:

select min(usenum) from T_ACCOUNT where year='2012'

查询结果:

(5)统计记录个数 count

需求:统计业主类型 ID 为 1 的业主数量

查询语句:

select count(*) from T_OWNERS t where ownertypeid=1

查询结果:

2. 分组聚合 Group by

需求:按区域分组统计水费合计数

查询语句:

select areaid,sum(money) from t_account group by areaid

查询结果:

3. 分组后条件查询 having

需求:查询水费合计大于 16900 的区域及水费合计

查询语句:

select areaid,sum(money) from t_account group by areaid
having sum(money)>169000

查询结果:

二、连接查询

(一)多表内连接查询

(1)需求:查询显示业主编号,业主名称,业主类型名称

查询语句:

select o.id 业主编号,o.name 业主名称,ot.name 业主类型
from T_OWNERS o,T_OWNERTYPE ot
where o.ownertypeid=ot.id

查询结果:

(2)需求:查询显示业主编号,业主名称、地址和业主类型

分析:此查询需要三表关联查询。分别是业主表,业主分类表和地址表

查询语句:

select o.id 业主编号,o.name 业主名称,ad.name 地址,
ot.name 业主类型
from T_OWNERS o,T_OWNERTYPE ot,T_ADDRESS ad
where o.ownertypeid=ot.id and o.addressid=ad.id

查询结果:

(3)需求:查询显示业主编号、业主名称、地址、所属区域、业主分类

分析:这里需要四个表关联查询,比上边多了一个区域表(T_AREA)

查询语句:

select o.id 业主编号,o.name 业主名称,ar.name 区域, ad.name 地
址, ot.name 业主类型 from T_OWNERS o ,T_OWNERTYPE ot,T_ADDRESS ad,T_AREA ar
where o.ownertypeid=ot.id and o.addressid=ad.id and ad.areaid=ar.id

查询结果:

(4)需求:查询显示业主编号、业主名称、地址、所属区域、收费员、业主分类

分析:此查询比上边又多了一个表 T_OPERATOR

查询语句:

select ow.id 业主编号,ow.name 业主名称,ad.name 地址,
ar.name 所属区域,op.name 收费员, ot.name 业主类型
from T_OWNERS ow,T_OWNERTYPE ot,T_ADDRESS ad ,
T_AREA ar,T_OPERATOR op
where ow.ownertypeid=ot.id and ow.addressid=ad.id
and ad.areaid=ar.id and ad.operatorid=op.id

查询结果:

(二)左外连接查询

需求:查询业主的账务记录,显示业主编号、名称、年、月、金额。如果此业主 没有账务记录也要列出姓名。

分析:我们要查询这个结果,需要用到 T_OWNERS(业主表) ,T_ACCOUNT (台账表) 按照查询结果,业主表为左表、账务表为右表。

按照 SQL1999 标准的语法,查询语句:

SELECT ow.id,ow.name,ac.year ,ac.month,ac.money
FROM T_OWNERS ow left join T_ACCOUNT ac
on ow.id=ac.owneruuid

按照 ORACLE 提供的语法,查询语句:

SELECT ow.id,ow.name,ac.year ,ac.month,ac.money FROM
T_OWNERS ow,T_ACCOUNT ac
WHERE ow.id=ac.owneruuid(+)

如果是左外连接,就在右表所在的条件一端填上(+)

查询结果:

(三)右外连接查询

需求:查询业主的账务记录,显示业主编号、名称、年、月、金额。如果账务记 录没有对应的业主信息,也要列出记录。

按照 SQL1999 标准的语法,查询语句:

select ow.id,ow.name,ac.year,ac.month,ac.money from
T_OWNERS ow right join T_ACCOUNT ac
on ow.id=ac.owneruuid

按照 ORACLE 提供的语法,查询语句:

select ow.id,ow.name,ac.year,ac.month,ac.money from
T_OWNERS ow , T_ACCOUNT ac
where ow.id(+) =ac.owneruuid

查询结果:

join使用参考:oracle的join的使用

三、子查询

(一)where 子句中的子查询

1. 单行子查询

  • 只返回一条记录
  • 单行操作符

需求:查询 2012 年 1 月用水量大于平均值的台账记录

查询语句:

select * from T_ACCOUNT
where year='2012' and month='01' and usenum>
( select avg(usenum) from T_ACCOUNT where year='2012' and month='01' )

查询结果:

2. 多行子查询

  • 返回了多条记录
  • 多行操作符

in 运算符

(1)需求:查询地址编号为 1 、3、4 的业主记录
分析:如果我们用 or 运算符编写,SQL 非常繁琐,所以我们用 in 来进行查询

查询语句:

select * from T_OWNERS where addressid in ( 1,3,4 )

查询结果:

(2)需求:查询地址含有“花园”的业主的信息

查询语句:

select * from T_OWNERS
where addressid in
( select id from t_address where name like '%花园%' )

查询结果:

(3)需求:查询地址不含有“花园”的业主的信息

查询语句:

select * from T_OWNERS
where addressid not in
( select id from t_address where name like '%花园%' )

查询结果:

(二)from 子句中的子查询

from 子句的子查询为多行子查询

需求:查询显示业主编号,业主名称,业主类型名称,条件为业主类型为”居民”, 使用子查询实现。

查询语句:

select * from (select o.id 业主编号,o.name 业主名称,ot.name 业主类型
               from T_OWNERS o,T_OWNERTYPE ot
               where o.ownertypeid=ot.id)
where 业主类型='居民'

查询结果:

(三)select 子句中的子查询

select 子句的子查询必须为单行子查询

(1)需求:列出业主信息,包括 ID,名称,所属地址。

查询语句:

select id,name,
(select name from t_address where id=addressid) addressname
from t_owners

查询结果:

(2)需求:列出业主信息,包括 ID,名称,所属地址,所属区域。

查询语句:

select id,name,
( select name from t_address where id=addressid )
addressname,
( select (select name from t_area where id=areaid ) from
t_address where id=addressid )
adrename
from t_owners;

查询结果:

四、分页查询

(一)简单分页

需求:分页查询台账表 T_ACCOUNT,每页 10 条记录

分析:我们在 ORACLE 进行分页查询,需要用到伪列 ROWNUM 和嵌套查询

查询语句:

select rownum,t.* from T_ACCOUNT t where rownum<=10

查询结果:

那么我们显示第 11 条到第 20 条的记录呢?编写语句:

select rownum,t.* from T_ACCOUNT t
where rownum>10 and rownum<=20

查询结果:空

嗯?怎么没有结果?
这是因为 rownum 是在查询语句扫描每条记录时产生的,所以不能使用“大于”
符号,只能使用“小于”或“小于等于” ,只用“等于”也不行。
那怎么办呢?我们可以使用子查询来实现

select * from
(select rownum r,t.* from T_ACCOUNT t where rownum<=20)
where r>10

查询结果:出来了

(二)基于排序的分页

需求:分页查询台账表 T_ACCOUNT,每页 10 条记录,按使用字数降序排序 。

我们查询第 2 页数据,如果基于上边的语句添加排序

查询语句:

select * from
(select rownum r,t.* from T_ACCOUNT t where rownum<=20 order
by usenum desc)
where r>10

查询结果:无序

经过验证,我们看到第 2 页的结果应该是下列记录

查询结果:

所以推断刚才的语句是错误的!那为什么是错误的呢?
我们可以先单独执行嵌套查询里面的那句话

select rownum r,t.* from T_ACCOUNT t
where rownum<=20 order by usenum desc

你会看到查询结果如下:

你会发现排序后的 R 是乱的。这是因为 ROWNUM 伪列的产生是在表记录扫描
是产生的,而排序是后进行的,排序时 R 已经产生了,所以排序后 R 是乱的。
那该如何写呢?
很简单,我们只要再嵌套一层循环(一共三层),让结果先排序,然后对排序后
的结果再产生 R,这样就不会乱了。

查询语句:

select * from
(select rownum r,t.* from
(select * from T_ACCOUNT order by usenum desc) t
where rownum<=20 )
where r>10

查询结果:排序正常

五、单行函数

(一)字符函数

函数图表:略

常用字符函数讲解:

(1)求字符串长度 LENGTH

查询语句:

select length('ABCD') from dual;

显示结果:

(2)求字符串的子串 SUBSTR

查询语句:

select substr('ABCD',2,2) from dual;

显示结果:

(3)字符串拼接 CONCAT

查询语句:

select concat('ABC','D') from dual;

显示结果:

我们也可以用|| 对字符串进行拼接

select 'ABC'||'D' from dual;

查询结果同上。

(二)数值函数

函数图表:略

常用数值函数讲解:

(1)四舍五入函数

查询语句:

select round(100.567) from dual

显示结果:
101

查询语句:

select round(100.567,2) from dual   

显示结果:
100.57

(2)截取函数 TRUNC

查询语句:

select trunc(100.567) from dual

显示结果:
100

查询语句:

select trunc(100.567,2) from dual

显示结果:
100.56

(3)取模 MOD

查询语句:

select mod(10,3) from dual

显示结果:
1

(三)日期函数

函数图表:略

我们用 sysdate 这个系统变量来获取当前日期和时间

查询语句:

select sysdate from dual

显示结果:
2023/9/20 16:28:50

常用日期函数讲解:

(1)加月函数 ADD_MONTHS :在当前日期基础上加指定的月

查询语句:

select add_months(sysdate,2) from dual

显示结果:
2023/11/20 16:29:57

(2)求所在月最后一天 LAST_DAY

查询语句:

select last_day(sysdate) from dual

显示结果:

(3)日期截取 TRUNC

查询语句:

select TRUNC(sysdate) from dual

显示结果:
2023/9/20

查询语句:

select TRUNC(sysdate,'yyyy') from dual

显示结果:
2023/1/1

查询语句:

select TRUNC(sysdate,'mm') from dual

显示结果:
2023/9/1

(四)转换函数

函数图表:略

常用转换函数讲解:

(1)数字转字符串 TO_CHAR

查询语句:

select TO_CHAR(1024) from dual

显示结果:

(2)日期转字符串 TO_CHAR

查询语句:

select TO_CHAR(sysdate,'yyyy-mm-dd') from dual

显示结果:
2023-09-20

查询语句:

select TO_CHAR(sysdate,'yyyy-mm-dd hh:mi:ss') from dual

显示结果:
2023-09-20 04:38:44

(3)字符串转日期 TO_DATE

查询语句:

select TO_DATE('2017-01-01','yyyy-mm-dd') from dual

显示结果:
2017/1/1

(4)字符串转数字 TO_NUMBER

查询语句:

select to_number('100') from dual

显示结果:
100

(五)其它函数

(1)空值处理函数 NVL

语法:
NVL(检测的值,如果为 null 的值);

查询语句:

select NVL(NULL,0) from dual

显示结果:
0

需求:
显示价格表中业主类型 ID 为 1 的价格记录,如果上限值为 NULL,则显示 9999999

查询语句:

select PRICE,MINNUM,NVL(MAXNUM,9999999)
from T_PRICETABLE where OWNERTYPEID=1

显示结果:

(2)空值处理函数 NVL2
语法:
NVL2(检测的值,如果不为 null 的值,如果为 null 的值);
需求:显示价格表中业主类型 ID 为 1 的价格记录,如果上限值为 NULL,显示“不限”.

查询语句:

select PRICE,MINNUM,NVL2(MAXNUM,to_char(MAXNUM) , '不限')
from T_PRICETABLE where OWNERTYPEID=1

显示结果:

(3)条件取值 decode

语法:
decode(条件,值 1,翻译值 1,值 2,翻译值 2,…值 n,翻译值 n,缺省值)
【功能】根据条件返回相应值

需求:显示下列信息(不要关联查询业主类型表,直接判断 1 2 3 的值)
查询语句:

select name,decode( ownertypeid,1,' 居 民 ',2,' 行 政 事 业 单 位
',3,'商业') as 类型 from T_OWNERS

显示结果:

上边的语句也可以用 case when then 语句来实现

查询语句:

select name ,(case ownertypeid
when 1 then '居民'
when 2 then '行政事业单位'
when 3 then '商业'
else '其它'
end
) from T_OWNERS

显示结果:

还有另外一种写法:

查询语句:

select name,(case
when ownertypeid= 1 then '居民'
when ownertypeid= 2 then '行政事业'
when ownertypeid= 3 then '商业'
end ) from T_OWNERS

显示结果:

六、行列转换

需求:按月份统计 2012 年各个地区的水费
查询语句:

select (select name from T_AREA where id= areaid ) 区域,
sum( case when month='01' then money else 0 end) 一月,
sum( case when month='02' then money else 0 end) 二月,
sum( case when month='03' then money else 0 end) 三月,
sum( case when month='04' then money else 0 end) 四月,
sum( case when month='05' then money else 0 end) 五月,
sum( case when month='06' then money else 0 end) 六月,
sum( case when month='07' then money else 0 end) 七月,
sum( case when month='08' then money else 0 end) 八月,
sum( case when month='09' then money else 0 end) 九月,
sum( case when month='10' then money else 0 end) 十月,
sum( case when month='11' then money else 0 end) 十一月,
sum( case when month='12' then money else 0 end) 十二月
from T_ACCOUNT where year='2012' group by areaid

显示结果:

需求:按季度统计 2012 年各个地区的水费

查询语句:

select (select name from T_AREA where id= areaid ) 区域,
       sum( case when month>='01' and month<='03' then money else
            0 end) 第一季度,
       sum( case when month>='04' and month<='06' then money else
            0 end) 第二季度,
       sum( case when month>='07' and month<='09' then money else
            0 end) 第三季度,
       sum( case when month>='10' and month<='12' then money else
            0 end) 第四季度
from T_ACCOUNT where year='2012' group by areaid

显示结果:

七、分析函数

以下三个分析函数可以用于排名使用。

(1) RANK 相同的值排名相同,排名跳跃
需求:对 T_ACCOUNT 表的 usenum 字段进行排序,相同的值排名相同,排名跳跃

查询语句:

select rank() over(order by usenum desc ),usenum from T_ACCOUNT

显示结果:

(2) DENSE_RANK 相同的值排名相同,排名连续
需求:对 T_ACCOUNT 表的 usenum 字段进行排序,相同的值排名相同,排名连 续

查询语句:

select dense_rank() over(order by usenum desc ),usenum from T_ACCOUNT

显示结果:

(3) ROW_NUMBER 返回连续的排名,无论值是否相等
需求:对 T_ACCOUNT 表的 usenum 字段进行排序,返回连续的排名,无论值是 否相等

查询语句:

select row_number() over(order by usenum desc ),usenum from T_ACCOUNT

显示结果:

用 row_number()分析函数实现的分页查询相对三层嵌套子查询要简单的多:
查询语句:

select * from
(select row_number() over(order by usenum desc )
rownumber,usenum from T_ACCOUNT)
where rownumber>10 and rownumber<=20

显示结果:

八、集合运算

(一)什么是集合运算

集合运算,集合运算就是将两个或者多个结果集组合成为一个结果集。集合运算
包括:
··UNION ALL(并集),返回各个查询的所有记录,包括重复记录。
··UNION(并集),返回各个查询的所有记录,不包括重复记录。
··INTERSECT(交集),返回两个查询共有的记录。
··MINUS(差集),返回第一个查询检索出的记录减去第二个查询检索出的记录之
后剩余的记录。

(二)并集运算

UNION ALL 不去掉重复记录

查询语句:

select * from t_owners where id<=7
union all
select * from t_owners where id>=5

显示结果:

UNION 去掉重复记录

查询语句:

select * from t_owners where id<=7
union
select * from t_owners where id>=5

显示结果:

(三)交集运算

查询语句:

select * from t_owners where id<=7
intersect
select * from t_owners where id>=5

显示结果:

(四)差集运算

查询语句:

select * from t_owners where id<=7
minus
select * from t_owners where id>=5

显示结果:

如果我们用 minus 运算符来实现分页,语句如下:

查询语句:

select rownum,t.* from T_ACCOUNT t where rownum<=20
minus
select rownum,t.* from T_ACCOUNT t where rownum<=10

显示结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小霸王_30037863

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值