一、函數–單行函數
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;
- 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;