Oracle 函數、分組子查詢

一、函數–單行函數

1.函數

1)理解:函數分爲系統內置函數和自定義函數。瞭解系統內
置函數(方法),重點掌握 to_date 、 to_char (字符和日期的轉換)

2)單行函數:一條記錄返回一個結果

3)多行函數 、組函數、聚合函數 :多條記錄返回一個結果

2.日期函數

1)理解:注意區分 db數據庫時間 ,java應用服務器的時間。以一方爲準 oracle以內部數字格式存儲日期:年,月,日,小時,分鐘,秒

2)當前時間 sysdate/current_date 以date類型返回當前的日期

-- 當前時間
select  distinct sysdate from emp;
-- 虛表
select distinct sysdate from dual;
select current_date from dual;

3)修改日期

-- 加減日期
-- 2天以後是幾號
select sysdate+2 from dual;
-- 所有員工入職的3天前是幾號
select hiredate,hiredate-3 from emp;

4)修改月份 add_months(d,x) 返回加上x月後的日期d的值

-- add_months(日期對象,月份數)
-- 查詢所有員工的試用期期到期(轉正的日期) 3個月試用期
select hiredate,add_months(hiredate,3) from emp;
-- 當前日期修改後三個月
select add_months(sysdate,3) from dual;

5)月份之差 months_between(date1,date2) 返回date1和date2之間月的數目

-- months_between(大月份,小月份)
-- 查詢所有員工到目前爲止一共工作了幾個月
select hiredate,months_between(sysdate,hiredate) from emp;

6)最後一天 LAST_DAY(d) 返回的所在月份的最後一天

-- last_day()
-- 查詢當前月的最後一天
select hiredate,last_day(hiredate) from emp;
select last_day(sysdate) day from dual;

7)下一個星期的時間 next_day(sysdate,‘星期一’) 下週星期一

-- 下一個星期三是幾號(即將要過的星期三)
select next_day(sysdate,'星期三') from dual;
select next_day(sysdate,5) from dual;

2.轉換函數

1)to_date(c,m) 字符串以指定格式轉換爲日期

-- to_date(數據,格式)
-- to_char(數據,格式)
-- 設定一個特定的時間(用一個特定的時間字符串轉換爲日期)
-- 設定一個時間   就是今天 '2020-2-5 09:18:25'
select to_date('2020/2/5 09:18:25','yyyy/mm/dd hh24:mi:ss')+3 from dual;
select to_date('2018/9/5 16:18:25','yyyy/mm/dd hh24:mi:ss')+3 from dual;

**2)to_char(d,m)**日期以指定格式轉換爲字符串

-- select to_char(sysdate,'yyyy-mm-dd-hh') from dual;
-- 將日期轉爲特定格式的字符串 
-- to_char
select to_char(sysdate,'yyyy"年"mm"月"dd"日" hh12:mi:ss') from dual;
select to_char(sysdate,'yyyy-mm-dd-hh') from dual;

3.其他函數

1) nvl (參數1,參數2) 如果參數1爲null,函數最終的結果爲參數2 ,如果參數1不爲null,結果還是參數1

select ename,nvl(comm,0) from emp;
select ename, nvl(to_char(comm),'hello') from emp;
  1. decode(判定字段,值1,結果1,值2,結果2,值3,結果3…(,默認結果))
-- 判定函數   decode(判定字段,值1,結果1,值2,結果2,值3,結果3....(,默認結果))
--給每個部門後後面添加一個僞列,如果10部門,僞列顯示爲十,二十,三十...
select deptno,dname,decode(deptno,10,'十',20,'二十',30,'三十',40,'四十') 中文部門編號 from dept;

3)case when then else end

-- 部門號10 工資漲10% 部門號20 工資漲8% 部門號30 工資漲15% 部門號40 工資漲20%
select ename, sal, deptno, (case deptno when 10 then sal * 1.1 when 20 then sal * 1.08 when 30 then sal * 1.15 else sal * 1.2 end) raisesal from emp;

-- 10部門漲薪10%, 20漲薪20%,30降薪1% , 40部門翻倍3倍
-- case when then else end
select ename,sal,deptno,(case deptno when 10 then sal*1.1 when 20 then sal*1.2 when 30 then sal*0.99 else sal*3 end) raisesal from emp;

二、組函數

組函數|聚合函數|多行函數 : 對結果集進行組函數計算,多行記錄返回一個結果
count(條件) sum(條件) max() min() avg()
注意: 組函數不能和非分組字段一起使用

1.count 統計記錄

-- 統計一下一共有多少個員工
select count(empno) from emp;
select count(deptno) from emp;
select deptno from emp;
select count(*) from emp;
-- 僞列
select count(1) from emp;
-- 統計一共有幾個部門 
select count(1) from dept;
-- 統計有員工存在的部門總數
-- 查詢有員工存在的部門編號的結果集,對這個結果集求個數
select count(distinct deptno) from emp;
select count(1) from dept where deptno in(select distinct deptno from emp);
-- 統計20部門一共有多少人
select count(deptno) from emp where deptno=20;
select count(*) from emp where deptno=20;

2.max min :最大值 最小值

-- 查詢本公司的最高工資和最低工資
select max(sal) from emp;--5000
select min(sal) from emp; --800
-- 查看30部門的最高工資和最低工資
select max(sal),min(sal) from emp where deptno=30;
-- 查詢 最高薪水的員工姓名, 及薪水
select max(sal) from emp;
select ename,sal from emp where sal=(select max(sal) from emp);

3.sum:求和

-- 計算本公司每個月一共要在工資上花費多少錢
select sum(sal) from emp;
select sum(comm) from emp;
select sum(sal+nvl(comm,0)) from emp;
-- 計算出所有員工的獎金總和  null 不參與運算
select sum(comm) from emp where comm is not null;

4.avg:平均值

-- 查詢工資低於平均工資的員工編號,姓名及工資
select empno,ename,sal from emp where sal<(select avg(sal) from emp);
-- avg 平均工資
select avg(sal) from emp;
-- 請查詢出 20部門的平均工資  組函數不能和非分組使用
select avg(sal) from emp where deptno=20;

三、分組

1.group by having

group by 分組字段
-- 查詢公式:select 數據 from 數據來源 where 行過濾條件 group by 分組字段1,.. having 過濾組信息(以組爲單位過濾) order by 排序字段..;
-- 執行流程: from -- where --group by --having --select  -- order by
-- 注意:
--  1)select 後如果出現了組函數|分了組,組函數不能與非分組字段,可以與其他組函數或分組字段一起使用
--  2)where 後不能使用組函數   因爲還沒有組,執行流程問題  

-- 求出所有有員工存在的部門編號
select deptno from emp group by deptno;
-- 找出20部門和30部門的最高工資 
	-- 20部門和30部門中的所有員工中的最高工資 
	select max(sal) from emp where deptno in(30,20);
	-- 找出20部門和30部門中每個部門的最高工資
 -- 先過濾 後分組
select max(sal),deptno from emp where deptno in(20,30) group by deptno;
-- 先分組再過濾
select max(sal),deptno from emp group by deptno having deptno in(20,30);
-- 求出每個部門的平均工資
-- 數據: 每組的平均薪資
-- 來源: 員工表 
-- 條件: 一個部門一個部門求平均薪資  ,一個部門一個值  以部門爲單位 如果不分組組函數對所有滿足條件的數據進行計算,如果分組了,以組爲單位
select avg(sal),deptno from emp group by deptno;
-- 求出每個部門員工工資高於1000的的部門平均工資
-- 數據: 部門平均工資
-- 來源: 員工表 
-- 條件: sal>1000 以部門爲單位:按照部門進行分組
select avg(sal),deptno from emp where sal>1000 group by deptno;
-- 求出10和20部門部門的哪些工資高於1000的員工的平均工資
select avg(sal),deptno from emp where sal>1000 group by deptno having deptno in(10,20);
-- 找出每個部門的最高工資
select max(sal) from emp group by deptno;
-- 求出每個部門的平均工資高於2000的部門編號和平均工資
-- 先過濾後分組select 後如果出現了組函數|分了組,組函數不能與非分組字段,
-- 可以與其他組函數或分組字段一起使用
  -- 2)where 後不能使用組函數   因爲還沒有組,執行流程問題
-- select deptno,avg(sal) from emp where avg(sal)>2000 group by deptno;
-- 先分組後過濾
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;
select * from emp;

四、子查詢與行轉列

1.一條sql語句實現需求

/*
id name course score
1 張三 語文 81
2 張三 數學 75
3 李四 語文 81
4 李四 數學 90
5 王五 語文 81
6 王五 數學 100
7 王五 英語 90
*/
-- 創建表
create table tb_student(
 id number(4) ,
 name varchar2(20),
 course varchar2(20),
 score number(5,2)
);
-- 插入數據
insert into tb_student values(1,'張三','語文',81);
insert into tb_student values(2,'張三','數學',75);
insert into tb_student values(3,'李四','語文',81);
insert into tb_student values(4,'李四','數學',90);
insert into tb_student values(5,'王五','語文',81);
insert into tb_student values(6,'王五','數學',100);
insert into tb_student values(7,'王五','英語',90);
commit; -- 提交
-- 刪除表
drop table tb_student cascade constraints;
-- 查表
select * from tb_student;
-- 使用一條sql語句,查詢每門課都大於80分的學生姓名
-- 數據: 學生姓名
-- 來源: tb_student
-- 條件: 1.學生考試科目數=一共有的科目數  and  2)這個人所有分數中最低分數>80
      -- 科目數
      select count(distinct course)from tb_student; 
      -- 每個人最低分
      select min(score) from tb_student group by name;
select name
  from tb_student
 group by name
having count(distinct course) = (select count(distinct course)
                                   from tb_student) and min(score) > 80;

2.行轉列

-- 行專列
select name,max(decode(course,'語文',score)) 語文,min(decode(course,'數學',score)) 數學,max(decode(course,'英語',score)) 英語 from tb_student group by name;
-- decode() 是單行函數
select name,decode(course,'語文',score) 語文, decode(course,'數學',score) 數學, decode(course,'英語',score) 英語 from tb_student;

五、rowid 和 rownum

1.rowid

rowid理解爲記錄在插入到數據庫的表中時候就存在的數據的地址(對象的地址),其實不是地址,根據地址得到的值
如果一個表中沒有主鍵,沒有不可重複的字段,可能會出現多條一模一樣的數據,無法區分重複數據,可以根據rowid進行區分

-- 當一個表中有多條一模一樣的數據的時候,實現去重,重複數據只保留一條
-- 查到要保留的數據
select id,name,course,score,min(rowid) from tb_student group by id,name,course,score; 
-- 更加好
select * from tb_student where rowid in(select min(rowid) from tb_student group by id,name,course,score);

-- 查到要刪除的數據
select *
  from tb_student
 where not
        rowid in
        (select min(rowid) from tb_student group by id, name, course, score);

-- 刪除這些數據
delete from tb_student
 where not
        rowid in
        (select min(rowid) from tb_student group by id, name, course, score);

2.rownum

rownum 結果集的序號 有一個結果集就有一個rownum select查到的結果集
rownum 從1開始,每次+1

-- rownum 從1開始,每次+1
select deptno,dname,loc,rowid,rownum from dept;
select empno,ename,rownum from emp where rownum<=4;

-- 分頁:在oracle中使用rownum.因爲rownum規律可循,控制rownum序號從1開始,每次+1,方便判斷
-- 查詢
-- 一般如果根據主鍵字段進行排序,先排序後確定rownum
select deptno,dname,rownum from dept order by deptno desc;
-- 一般如果根據非主鍵字段進行排序,先確定rownum再排序
select deptno,dname,rownum from dept order by loc;

-- 保證一定先排序後確定rownum,在結果集的外面嵌套一層select,這個select的rownum肯定就是從1開始,根據這個有規律的,已確定的row進行判斷操作就可以
select deptno,dname,rownum num from dept order by loc;

select rownum,deptno,dname,num from (select deptno,dname,rownum num from dept order by loc);

select empno,ename,sal,comm,rownum from (select empno,ename,sal,comm,rownum num from emp order by sal desc); 

-- 分頁需求:
-- i頁數  num每頁顯示幾個
-- num= 3  i=4
-- 每一頁要顯示的數據的rownum   第一個:  rownum>=num*(i-1)+1                    最後一個爲: row<=num*i
select *
  from (select empno, ename, sal, comm, rownum num2
          from (select empno, ename, sal, comm, rownum num
                  from emp
                 order by sal desc))
 where num2 >= 3 * (1 - 1) + 1
   and num2 <= 3 * 1;

發佈了28 篇原創文章 · 獲贊 2 · 訪問量 1185
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章