oracle基础语法(二)ORACLE查询
第二天 ORACLE查詢
注意:
1、and的優先級比or大,所以我們需要用 ( ) 來改變優先級。
2、HAVING 子句不能離開GROUP BY 子句單獨使用,HAVING 子句無法完成代替WHERE 子句
3、在SELECT 列表中所有****未包含在聚合函數*中的*列****都應該包含在 GROUP BY 子句中。反之,包含在 GROUP BY 子句中的列不必包含在SELECT 列表中
4、**在分組時使用Where子句和Having子句的本質區別:**使用having子句過濾,是先分組,再過濾,注意:分組的時候是全表掃描的,效率較低。使用where子句過濾,是先過濾再分組,注意:分組的時候僅需要掃描部分數據,效率較高。結論:從語法上看,兩者選擇簡單歸納為,就是group by分組之后需要的條件中有組函數的,就必須得用having,其他都可以直接用where。從性能上看,實際開發中,使用分組的時候盡量先加一個where 的過濾條件。沒有組函數的情況下,盡量選擇where
5、rowid:物理地址行;使用場景:用來做去重復記錄。rownum:返回查詢結果的行號。可以限制查詢結果集中返回的行數。
第一章 單表查詢(掌握)
1、簡單條件查詢
1、精準查詢
需求:查詢水表編號為30408的業主記錄
-- 查詢水表編號為30408的業主記錄 select * from t_owners where watermeter = 30408;查詢結果:
2、模糊查詢
需求:查詢業主名稱包含“劉”的業主記錄
查詢語句:
-- 查詢業主名稱包含 “劉”的業主記錄 select * from t_owners where name like '%劉%'查詢結果:
3、and運算符
需求:查詢業主名稱包含“劉”的并且門牌號包含5的業主記錄
查詢語句:
-- 查詢業主名稱包含“劉”的并且門牌號包含5的業主記錄 select * from t_owners where name like '%劉%' and housenumber like '%5%'查詢結果:
4、or運算符
需求:查詢業主名稱包含“劉”的或者門牌號包含5的業主記錄
查詢記錄:
-- 查詢業主名稱包含“劉”的或者門牌號包含5的業主記錄 select * from t_owners where name like '%劉%' and housenumber like '%5%'查詢結果:
5、and 與 or 運算符混合使用
需求:查詢業主名稱包含“劉”的或者門牌號包含5的業主記錄,并且地址編號為3的記錄。
語句:
-- 查詢業主名稱包含“劉”的或者門牌號包含5的業主記錄,并且地址編號為3的記錄。 select * from t_owners where (name like '%劉%' or housenumber like '%5%') and addressid = 3因為and的優先級比or大,所以我們需要用 ( ) 來改變優先級。
查詢結果:
6、范圍查詢
需求:查詢賬單記錄中用水字數大于等于10000,并且小于等于20000的記錄
我們可以用>= 和 <= 來實現:
--查詢賬單記錄中用水字數大于等于10000,并且小于等于20000的記錄 select * from t_account where usenum >= 10000 and usenum <= 20000;我們也可以用between … and … 來實現:
-- 使用 between ... and .. select * from t_account where usenum between 10000 and 20000;查詢結果:
7、空值查詢
需求:查詢T_PRICETABLE表中MAXNUM為空的記錄
語句:
-- 查詢T_PRICETABLE表中MAXNUM為空的記錄 select * from t_pricetabel where maxnum is null;查詢結構:
需求:查詢T_PRICETABLE表中MAXNUM不為空的記錄
語句:
-- 查詢T_PRICETABLE表中MAXNUM不為空的記錄 select * from t_pricetabel where maxnum is not null;查詢結果:
2、去掉重復記錄
需求:查詢業主表中得地址ID ,不重復顯示
語句:
-- 查詢業主表中得地址ID ,不重復顯示 selct distinct addressid from t_owners查詢結果:
3、排序查詢
1、升序排序
需求:對T_ACCOUNT表按使用量進行升序排序
語句:
--需求:對T_ACCOUNT表按使用量進行升序排序 select * from t_account order by usenum -- 默認為升序 ASC查詢結果:
2、降序排序
需求:對T_ACCOUNT 表按使用量進行降序排序
語句:
-- 對T_ACCOUNT 表按使用量進行降序排序 select * from t_account order by usenum DESC -- DESC為降序關鍵字查詢結果:
問題:SELECT語句的執行效率
select * from t_owners;-- 數據庫進行全字段掃描,在查詢 select id,name,addressid,housenumber, watermeter,adddate,ownertypeid from t_owners; -- 指定字段后省去了數據庫的全字段掃描 -- 結論:在開發中盡量指定sql語句的字段4、聚合統計
ORACLE的聚合統計是通過分組函數來實現的,與mysql一致。
1、聚合函數
(1)求和 sum
需求:統計2012年所有用戶的用水量總和
-- 統計 2012年所有用戶的用水量總和 select sum(usenum) from t_account where year = '2012'查詢結果如下:
(2)求平均 avg
需求:統計2012 年所有用水量(字數)的平均值
-- 統計 2012年所有用水量(字數)的平均值 select avg(usenum) from t_account where year = '2012';查詢結果如下:
(3)求最大值 max
需求:統計2012年最高用水量(字數)
-- 統計2012年最高用水量(字數) select max(usenum) from t_account where year = '2012';查詢結果如下:
(4)求最小值min
需求:統計2012年最低用水量(字數)
-- 統計2012年最低用水量(字數) select min(usenum) from t_account where year = '2012';查詢結果如下:
(5)統計記錄個數 count
需求:統計業主類型ID為1的業主數量
-- 統計業主類型ID為1的業主數量 select count(*) from t_owbers where ownertypeid =1 ;查詢結果如下:
*2. 分組聚合Group by*
需求:按區域分組統計水費合計數
語句:
-- 按區域分組統計水費合計數 select areaid,sum(money) from t_account group by areaid查詢結果:
注意:
在select 列表中所有未包含在聚合函數中的列都應該包含在GROUP BY 子句中。
反之,包含在 GROUP BY子句中的列不必包含在select類表中
*3. 分組后條件查詢 having*
需求:查詢水費合計大于169000的區域及水費合計
語句:
-- 查詢水費合計大于169000的區域及水費合計 select areaid,sum(money) from t_account group by areaid having sum(money)>169000;查詢結果:
注意事項:
? HAVING 子句不能離開GROUP BY 子句單獨使用,HAVING 子句無法完成代替WHERE
子句
在分組時使用where 子句和having子句的本質的區別:
使用having子句過濾,是先分組,再過濾,注意:分組的時候是全表掃描的,效率較低。
使用where子句過濾,是先過濾在分組,注意:分組的時候僅需要掃描部分數據,效率較高。
結論:
從語法上看,兩者選擇簡單的歸納為,就是group by 分組之后需要的條件中有組函數的,就
必須得用having,其他都直接用where
從性能上述看:實際開發中,使用分組的時候盡量先加一個where的過濾條件。沒有組函數的情況下,盡量選擇where
5、基于偽劣的查詢
在oracle的表的使用過程中,實際表中還有一些附加的列,稱為虛擬列(虛擬列)。
偽列就像表中的列一樣,但是在表中并不存儲。偽列是由oracle進行維護和管理的,用戶只能查詢,不能進行增刪改操作。在sql語句中想要獲取偽列的值必須要顯式指定偽列。
接下來學習兩個偽列:ROWID 和 ROWNUM。
1、ROWID
表中的每一行在數據文件中都有一個物理地址,ROWID偽列返回的就是該行的物理地址。使用ROWID可以快速的定位表中的某一行。ROWID值可以唯一的標識表中的一行。由于ROWID返回的是該行的物理地址,因此使用ROWID可以顯示行是如何存儲的。
查詢語句:
-- 查詢時使用ROWID,需要注意:必須顯式的指定POWID select rowid,t.* from t_area t; --在查詢時指定了列名后,就不能直接使用*,如果要使用,必須是:表的名稱.*查詢結果如下:
我們可以通過指定ROWID來查詢記錄
select rowID,T.* from T_AREA t where ROWID='AAAM1uAAGAAAAD8AAC';查詢結果如下:
ROWID的組成:
數據對象編號 AAAM1u 數據對象制定的就表
相對數據文件號 AAG 文件號就是指定數據文件編號
數據塊號 AAAAD8
數據行號 AAC
rowidd的使用場景:用來做去重記錄。
2、ROWNUM
在查詢的結果集中,ROWNUM為結果集中每一行標識一個行號,第一行返回1,第二行返回2,以此類推。通過ROWNUM偽列可以限制查詢結果集中返回的行數。
查詢語句:
select rownum,t.* from T_OWNERTYPE t查詢結果如下:
第二章連接查詢(重點)
在MYSQL數據庫中接觸:內連接、左外連接、右外連接、完全外連接(左連接+右連接)
1. 多表內連接查詢
(1)需求:查詢顯示業主編號,業主名稱,業主類型名稱,如下圖:
查詢語句:
-- 查詢顯示業主編號,業主名稱,業主類型名稱 /* 業主表(o):業主編號、業主名稱 業主類型id 業主類型表(ot):業主類型名稱 id */ select o.id "業主編號",o.name "業主名稱",ot.name "業主類型名稱" from t_owners o ,t_ownertype ot where o.ownertypeid = ot.id(2)需求:查詢顯示業主編號,業主名稱、地址和業主類型,如下圖
分析:此查詢需要三表關聯查詢。分別是業主表,業主分類表和地址表
語句:
(3)需求:查詢顯示業主編號、業主名稱、地址、所屬區域、業主類型,如下圖:
分析:這里需要四個表關聯查詢,比上邊多了一個區域表(T_AREA)
查詢語句:
(3)需求:查詢顯示業主編號、業主名稱、地址、所屬區域、業主類型,如下圖:
(4)需求:查詢顯示業主編號、業主名稱、地址、所屬區域、收費員、業主類型,如下圖:
分析:此查詢比上邊又多了一個表 T_OPERATOR
語句:
2、左外連接查詢
需求:查詢業主的賬務記錄,顯示業主編號、名稱、年、月、金額。如果此業主沒有賬務記錄也要列出姓名。
按照SQL1999標準的語法,查詢語句如下:
按照ORACLE提供的語法,就很簡單了:
SELECT ow.id,ow.name,ac.year ,ac.month,ac.money FROM T_OWNERS ow,T_ACCOUNT ac WHERE ow.id=ac.owneruuid(+)如果是左外連接,就在左表所在的條件一端填上(+)
3. 右外連接查詢
需求:查詢業主的賬務記錄,顯示業主編號、名稱、年、月、金額。如果賬務記錄沒有對應的業主信息,也要列出記錄。如下圖:
SQL1999標準的語句
ORACLE的語法
如果是右外連接,就在左表所在的條件一端填上(+)**
第三章 子查詢 (掌握)
子查詢:在一個查詢中包含另外一個查詢語句
例如:select * from(select id,name from User)
select id ,(select name from user) from 表
1、單行子查詢
- 內部查詢只返回一條記錄
- 單行操作符
需求:查詢2012年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、多行子查詢
- 內部查詢返回了多條記錄
- 多行操作符
1、in 運算符
(1)需求:查詢地址編號為1 、3、4 的業主記錄
分析:如果我們用or運算符編寫,sql非常繁瑣,所以我們用in來進行查詢
語句如下:
--查詢地址編號為1 、3、4 的業主記錄(使用or運算符) select * from t_owners where addressid = 1 or address = 3 or addressid =4; --查詢地址編號為1 、3、4 的業主記錄(使用in) select * from t_owners where address 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 '%花園%');查詢結果:
2、all運算符
需求:查詢2012年賬單中,使用量大于2012年3月最大使用量的賬單數據
分析:此查詢除了可以用max函數來實現查詢
-- 查詢2012年賬單中,使用量大于2012年3月最大使用量的賬單數據 -- 外查詢:查2012年賬單信息; 條件:使用量大于2012年3月最大使用量 -- 子查詢:查詢2012年3月最大使用量 select * from t_account where usenum > (select maxz(usenum) from t_account where year='2012' and month = '03');此處之外,還可以使用all運算符來實現相同的效果,語法如下:
select * from t_account where usenum > all(select usenum from t_account where year = '2012' and month = '03');查詢結果如下:
第四章 分頁查詢(重點)
MySQL中的分頁語句:select * from T_OWNERS LIMIT 3,3;
1、簡單分頁
需求:分頁查詢賬單表T_ACCOUNT,每頁10條記錄
分析1:我們在ORACLE進行分頁查詢,需要用到偽列ROWNUM 。
我們首先顯示前10條記錄,語句如下:
/*簡單分頁 分頁查詢賬單表 T_ACCOUNT,每頁10 條記錄 */ -- 首先:先顯示前10條記錄 select rownum,t.* from t_account t where rownum <=10;顯示結構如下;
那么我們顯示第11條到第20條的記錄呢?編寫語句:
-- 顯示第11條到第20條的記錄 select rownum,t.* from t_account t where rownum > 10 and rownum <= 20;查詢結果:
嗯?怎么沒有結果?
這是因為rownum是在查詢語句掃描每條記錄時產生的,所以不能使用“大于”或“大于等于”符號,只能使用“小于”或“小于等于” 。(只用“等于”也不行)
ROWNUM產生過程: rownum是基于ORACLE在掃描表中每條記錄時產生,表中的記錄是逐行掃描,每掃描到一行,rownum就賦予一個行號
那怎么辦呢?
分析2:在oracle中進行分頁查詢,除了要用到偽列rownum,還需要嵌入查詢(子查詢)。
-- 使用偽列rownum和嵌套查詢,進行分頁(第11條到第20條的記錄) select * from (select rownum rm,t.* from t_account t where rownum <=20 ) where rm>10;查詢結果如下:
2、基于排序的分頁
需求:分頁查詢賬單表T_ACCOUNT,每頁10條記錄,按使用字數(usenum)降序排序。
我們查詢第2頁數據,如果基于上邊的語句添加排序,語句如下:
/*基于排序的分頁 分頁查詢賬單表T_ACCOUNT,每頁10條記錄,按使用字數(USENUM)降序排序 */ -- 查詢第二頁;第10條記錄到第20條記錄 select * from (select rownum rm,t.* from t_account t where rownum <= 20 order by usenum desc) where rm > 10;查詢結果如下:
經過驗證,我們看到第2頁的結果應該是下列記錄
所以推斷剛才的語句是錯誤的!那么什么是錯誤的呢?
我們可以先單獨執行嵌套查詢里面的那句話
select rownum r,t.* from T_ACCOUNT t where rownum<=20 order by usenum desc你會看到查詢結果如下:
你會發現排序后的rownum是亂序的。這是因為rownum偽列的產生是在表記錄掃描時產生的,而排序是后進行的,而排序是后進行的,排序時ROWNUM已經產生了,所以排序后rownum是亂的。
那該如何寫呢?
很簡單,我們只要再嵌套一層循環(一共三層),讓結果先排序,然后對排序后的結果再產生ROWNUM,這樣就不會亂了。
語句如下:
select * from (select rownum r,t.* from (select * from T_ACCOUNT order by usenum desc) t where rownum <=20 ) where r>10結果如下:
第五章 單行函數(掌握)
1、字符函數
| ASCII | 返回對應字符的十進制值 |
| CHR | 給出十進制返回字符 |
| CONCAT | 拼接兩個字符串,與 || 相同 |
| INITCAP | 將字符串的第一個字母變為大寫 |
| INSTR | 找出某個字符串的位置 |
| INSTRB | 找出某個字符串的位置和字節數 |
| LENGTH | 以字符給出字符串的長度 |
| LENGTHB | 以字節給出字符串的長度 |
| LOWER | 將字符串轉換成小寫 |
| LPAD | 使用指定的字符在字符的左邊填充 |
| LTRIM | 在左邊裁剪掉指定的字符 |
| RPAD | 使用指定的字符在字符的右邊填充 |
| RTRIM | 在右邊裁剪掉指定的字符 |
| REPLACE | 執行字符串搜索和替換 |
| SUBSTR | 取字符串的子串 |
| SUBSTRB | 取字符串的子串(以字節) |
| SOUNDEX | 返回一個同音字符串 |
| TRANSLATE | 執行字符串搜索和替換 |
| TRIM | 裁剪掉前面或后面的字符串 |
| UPPER | 將字符串變為大寫 |
常用的字符函數講解:
(1)求字符串長度LENGTH
語句:
-- 求字符串長度 LENGTH select length('ABCD') from dual; -- 說明:dual 是ORACLE 的內部表(虛表),表中僅有一行一列。顯示結果為:
(2)字符串拼接CONCAT
語句:
-- 字符串拼接concat select concat('ABC','D') from dual;查詢結果如下
我們也可以用||對字符串進行拼接
-- 字符串拼接,使用“||”符號 select 'ABC' || 'D' FROM DUAL;(3)字符串替換REPLACE
語句:
-- 字符串替換 replace select replace('ADBCD','D','d') from dual;查詢結果如下:
問題:請問 select replace(‘ADBCD’,‘D’) from dual 執行結果?
答案:把姓名中所有的A全部刪除掉select replace('ADBCD','D') from dual ;(4)求字符串的子串substr
語句:
-- 獲取子字符串substr(字符串,起始位置,截取長度) select substr('ABCD',2,2) from dual;顯示結果為:
問題:以下查詢執行完成后,結果是什么?
select substr('Jackie',2) from dual;-- 從左邊位置2開始截取,截取到最后 select substr('Jackie',2,0) from dual;-- 從左邊位置2開始截取,截取0個,就相當于沒有截取。取值為空字符串 select substr('Jackie',2.9,3.2) from dual;-- 先把小數轉為整數(不會四舍五入),在截取 select substr('Jackie',-4,2) from dual; -- 從右邊位置開始截取2位;參數2:從右邊取n位;參數3:取出的結果要m個值面試題:請問substr()函數截取時下標是從0 還是從1開始?
答案:對oracle來說,substr下標從0或從1都不會有問題,而下標還可寫成負數形式,表示從后向取值2. 數值函數
| ABS(value) | 絕對值 |
| CEIL(value) | 大于或等于value的最小整數 |
| COS(value) | 余弦 |
| COSH(value) | 反余弦 |
| EXP(value) | e的value次冪 |
| FLOOR(value) | 小于或等于value的最大整數 |
| LN(value) | value的自然對數 |
| LOG(value) | value的以10為底的對數 |
| MOD(value,divisor) | 求模 |
| POWER(value,exponent) | value的exponent次冪 |
| ROUND(value,precision) | 按precision 精度4舍5入 |
| SIGN(value) | value為正返回1;為負返回-1;為0返回 0. |
| SIN(value) | 余弦 |
| SINH(value) | 反余弦 |
| SQRT(value) | value 的平方根 |
| TAN(value) | 正切 |
| TANH(value) | 反正切 |
| TRUNC(value,按precision) | 按照precision 截取value |
| VSIZE(value) | 返回value在ORACLE的存儲空間大小 |
常用數值函數講解:
(1)四舍五入函數ROUND
語句:
-- 數值函數:round(四舍五入) select round(100.567) round dual;查詢結果如下:
語句:
-- 數值函數:round(數值,小數位數) select round(100.567,2) from dual;查詢結果如下:
**
(2)截取函數TRUNC
語句:
-- 數值函數:trunc 不會四舍五入,直接截取 select trunc(100.567) from dual;查詢結果:
**
語句:
-- 數值函數:trunc select trunc(100.567,2)from dual;
(3)取模MOD
語句:
select mod(10,3) from dual;結果:
3. 日期函數
| ADD_MONTHS | 在日期date上增加count個月 |
| GREATEST(date1,date2,. . .) | 從日期列表中選出最晚的日期 |
| LAST_DAY( date ) | 返回日期date 所在月的最后一天 |
| LEAST( date1, date2, . . .) | 從日期列表中選出最早的日期 |
| MONTHS_BETWEEN(date2,date1) | 給出 Date2 - date1 的月數(可以是小數) |
| NEXT_DAY( date,’day’) | 給出日期date之后下一天的日期,這里的day為星期,如: MONDAY,Tuesday等。 |
| NEW_TIME(date,’this’,’other’) | 給出在this 時區=Other時區的日期和時間 |
| ROUND(date,’format’) | 未指定format時,如果日期中的時間在中午之前,則將日期中的時間截斷為12 A.M.(午夜,一天的開始),否則進到第二天。時間截斷為12 A.M.(午夜,一天的開始),否則進到第二天。 |
| TRUNC(date,’format’) | 未指定format時,將日期截為12 A.M.( 午夜,一天的開始). |
我們用sysdate這個系統變量來獲取當前日期和時間。
語句如下:
select sysdate from dual;--獲取當前系統的日期時間查詢結果如下:
常見日期函數講解:
(1)加月函數ADD_MODTHS:在當前日期基礎上加指定的月
語句:
-- 日期函數:ADD_MODTHS 在指定日期的基礎上增加或減少月份值 select add_months(sysdate,2) from dual;查詢結果如下:
問題:執行下面sql語句會顯示什么?
select add_months(sysdate,-2) from dual;(2)求所在月最后一天LAST_DAY
語句:
-- 日期函數:LAST_DAY獲指定日期所屬當月的最后一天 SELECT last_day(sysdate) from dual; select last_day(add_months(sysdate,1)) from dual;(3)日期截取TRUNC
語句:
-- 日期函數:trunc 截取指定日期中的指定值(可以是年、月、日、時、分、秒) select trunc(sysdate) from dual;-- 截取掉時間值,保留日期值查詢結果如下:
語句:
select trunc(sysdate,'yyyy') from dual;-- 按年截取(保留年份,月和日為初始值1)查詢結果如下:
語句:
select trunc(sysdate,'mm') from dual;-- 按月截取(保留年和月,日的初始值為1)查詢結果如下:
select trunc(sysdate,'dd') from dual;-- 按日截取 select trunc(sysdate,'hh') from dual;-- 按時截取 select trunc(sysdate,'mi') from dual;-- 按分截取4. 轉換函數
| CHARTOROWID | 將 字符轉換到 rowid類型 |
| CONVERT | 轉換一個字符節到另外一個字符節 |
| HEXTORAW | 轉換十六進制到raw 類型 |
| RAWTOHEX | 轉換raw 到十六進制 |
| ROWIDTOCHAR | 轉換 ROWID到字符 |
| TO_CHAR | 轉換日期格式到字符串 |
| TO_DATE | 按照指定的格式將字符串轉換到日期型 |
| TO_MULTIBYTE | 把單字節字符轉換到多字節 |
| TO_NUMBER | 將數字字串轉換到數字 |
| TO_SINGLE_BYTE | 轉換多字節到單字節 |
常用轉換函數
(1)數字轉字符串TO_CHAR
語句:
-- 轉換函數:to_char select to_char(1024) from dual; -- 把數字轉為字符串查詢結果:
select to_char(123456789,'000,000,000') from dual; -- 把數字按格式轉為字符串(2)日期轉字符串
語句:
-- 轉換函數:把日期按照指定格式轉為字符串 select to_char(sysdate,'yyyy-mm-dd') from dual;查詢結果:
語句:
select to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual;查詢結果:
語句:
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual; --小時是按24小時制查詢結果:
語句:
select to_char(sysdate,'yyyy-fmmm-fmdd fmhh:fmmi:fmss') from dual;-- 轉換的時候去除0查詢結果:
語句:
select to_char(sysdate,'yyyy') from dual; --截取年查詢結果:
語句:
select to_char(sysdate,'yyyy"年"mm"月"dd"日"hh"時"mi"分"ss"秒"') from dual;查詢結果:
擴展內容:
使用to_char(sysdate,‘HH’); ‘HH’ 可以使用如下表中的參數替換
| HH | 一天的小時數 (01-12) |
| HH12 | 一天的小時數 (01-12) |
| HH24 | 一天的小時數 (00-23) |
| MI | 分鐘 (00-59) |
| SS | 秒 (00-59) |
| SSSS | 午夜后的秒 (0-86399) |
| AM or A.M. or PM or P.M. | 正午標識(大寫) |
| am or a.m. or pm or p.m. | 正午標識(小寫) |
| Y,YYY | 帶逗號的年(4 和更多位) |
| YYYY | 年(4和更多位) |
| YYY | 年的后三位 |
| YY | 年的后兩位 |
| Y | 年的最后一位 |
| MONTH | 全長大寫月份名(9字符) |
| Month | 全長混合大小寫月份名(9字符) |
| month | 全長小寫月份名(9字符) |
| MON | 大寫縮寫月份名(3字符) |
| Mon | 縮寫混合大小寫月份名(3字符) |
| mon | 小寫縮寫月份名(3字符) |
| MM | 月份 (01-12) |
| DAY | 全長大寫日期名(9字符) |
| Day | 全長混合大小寫日期名(9字符) |
| day | 全長小寫日期名(9字符) |
| DY | 縮寫大寫日期名(3字符) |
| Dy | 縮寫混合大小寫日期名(3字符) |
| dy | 縮寫小寫日期名(3字符) |
| DDD | 一年里的日子(001-366) |
| DD | 一個月里的日子(01-31) |
| D | 一周里的日子(1-7;SUN=1) |
| W | 一個月里的周數 |
| WW | 一年里的周數 |
| CC | 世紀(2 位) |
| J | Julian 日期(自公元前4712年1月1日來的日期) |
| Q | 季度 |
(3)字符串轉日期TO_DATE
語句:
select to_date('2017-01-01','yyyy-mm-dd') from dual; --把字符串按指定格式轉為日期查詢結果如下:
(4)字符串轉數字TO_NUMBER
語句:
select to_number('100') from dual;5. 其它函數(重點)
(1)空值處理函數 NVL
用法:
NVL(檢測的值,如果為null的值)
語句:
select NVL(NULL,0) from dual;查詢結果如下:
需求:
顯示價格表中業主類型ID為1的價格記錄,如果上限值為NULL,則顯示9999999
語句:
--顯示價格表中業主類型ID為1的價格記錄,如果上限值為NULL,則顯示9999999 select price,minnum,NVL(maxnum,9999999) from t_pricetable where ownertypeid = 1;查詢結果:
(2)空值處理函數 NVL2
用法:
NVL2(檢測的值,如果不為null的值,如果為null的值);
需求:顯示價格表中業主類型ID為1的價格記錄,如果上限值為NULL,顯示“不限”
(3)條件取值 decode
DECODE()函數:多數值判斷,類似于if … else 語句,不同的是decode()判斷的是數值
? 而不是邏輯條件
在SQL優化中,推薦DECODE(),可以減少I/O次數
語法:
decode(條件,值1,翻譯值1,值2,翻譯值2....,缺省值) 【功能】 根據條件返回相應值需求:顯示下列信息(不要關聯查詢業主類型表,直接判斷1 2 3 的值)
語句:
-- 顯示下列信息(不要關聯查詢業務類型表,直接判斷1 2 3的值) select NAME,DECODE(ownertypeid,1,'居民',2,'行政事業單位',3,'商業') as "類型" from t_owners;上邊的語句也可以用case when then 語句來實現
select name,( case ownertypeidwhen 1 then '居民'when 2 then '行政事業單位'when 3 then '商業'end ) as 類型 from t_owners;還有另外一種寫法:
select name,(case when ownertypeid = 1 then '居民' when ownertypeid = 2 then '行政事業單位' when ownertypeid = 3 then '商業' else '其他' END ) AS 類型 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. 什么是集合運算
集合運算,集合運算就是將兩個或者多個結果集組合成為一個結果集。
集合運算包括:
UNION ALL(并集),返回各個查詢的所有記錄,包括重復記錄。
UNION(并集),返回各個查詢的所有記錄,不包括重復記錄。
INTERSECT(交集),返回兩個查詢共有的記錄。
MINUS(差集),返回第一個查詢檢索出的記錄減去第二個查詢檢索出的記錄之后剩余的記錄。
2、并集運算
UNION ALL 不去掉重復記錄
結果如下:
UNION 去掉重復記錄
3. 交集運算
結果:
4. 差集運算
結果:
如果我們用minus運算符來實現分頁,語句如下:
結果:
第八章 綜合案例
為《自來水收費系統》開發統計模塊相關的功能
1.收費日報單(總)
統計某日的收費,按區域分組匯總,效果如下:
語句:
select (select name from T_AREA where id= areaid ) 區域, sum(usenum)/1000 "用水量(噸)" ,sum(money) 金額 from T_ACCOUNT where to_char(feedate,'yyyy-mm-dd')='2012-05-14' group by areaid2.收費日報單(收費員)
統計某收費員某日的收費,按區域分組匯總,效果如下:
語句:
select (select name from T_AREA where id= areaid ) 區域, sum(usenum)/1000 "用水量(噸)" ,sum(money) 金額 from T_ACCOUNT where to_char(feedate,'yyyy-mm-dd')='2012-05-14' and feeuser=2 group by areaid3.收費月報表(總)
統計某年某月的收費記錄,按區域分組匯總
語句:
select (select name from T_AREA where id= areaid ) 區域, sum(usenum)/1000 "用水量(噸)" ,sum(money) 金額 from T_ACCOUNT where to_char(feedate,'yyyy-mm')='2012-05' group by areaid*4.收費月報表(收費員)*
統計某收費員某年某月的收費記錄,按區域分組匯總
語句:
select (select name from T_AREA where id= areaid ) 區域, sum(usenum)/1000 "用水量(噸)" ,sum(money) 金額 from T_ACCOUNT where to_char(feedate,'yyyy-mm')='2012-05' and feeuser=2 group by areaid*5.收費年報表(分區域統計)*
統計某年收費情況,按區域分組匯總,效果如下:
語句:
select (select name from T_AREA where id= areaid ) 區域, sum(usenum)/1000 "用水量(噸)" ,sum(money) 金額 from T_ACCOUNT where to_char(feedate,'yyyy')='2012' group by areaid*6.收費年報表(分月份統計)*
統計某年收費情況,按月份分組匯總,效果如下
語句:
select to_char(feedate,'mm') 月份,sum(usenum)/1000 使用噸數,sum(money) 金額 from T_ACCOUNT where to_char(feedate,'yyyy')='2013' GROUP BY to_char(feedate,'mm') ORDER BY to_char(feedate,'mm')*7.收費年報表(分月份統計)*
統計某年收費情況,按月份分組匯總,效果如下
語句:
select '用水量(噸)' 統計項,sum (case when to_char(feedate,'mm')='01' then usenum else 0 end )/1000 一月,sum (case when to_char(feedate,'mm')='02' then usenum else 0 end )/1000 二月,sum (case when to_char(feedate,'mm')='03' then usenum else 0 end )/1000 三月,sum (case when to_char(feedate,'mm')='04' then usenum else 0 end )/1000 四月,sum (case when to_char(feedate,'mm')='05' then usenum else 0 end )/1000 五月,sum (case when to_char(feedate,'mm')='06' then usenum else 0 end )/1000 六月,sum (case when to_char(feedate,'mm')='07' then usenum else 0 end )/1000 七月,sum (case when to_char(feedate,'mm')='08' then usenum else 0 end )/1000 八月,sum (case when to_char(feedate,'mm')='09' then usenum else 0 end )/1000 九月,sum (case when to_char(feedate,'mm')='10' then usenum else 0 end )/1000 十月,sum (case when to_char(feedate,'mm')='11' then usenum else 0 end )/1000 十一月,sum (case when to_char(feedate,'mm')='12' then usenum else 0 end )/1000 十二月 from T_ACCOUNT where to_char(feedate,'yyyy')='2013' UNION ALL select '金額(元)' 統計項,sum (case when to_char(feedate,'mm')='01' then money else 0 end ) 一月,sum (case when to_char(feedate,'mm')='02' then money else 0 end ) 二月,sum (case when to_char(feedate,'mm')='03' then money else 0 end ) 三月,sum (case when to_char(feedate,'mm')='04' then money else 0 end ) 四月,sum (case when to_char(feedate,'mm')='05' then money else 0 end ) 五月,sum (case when to_char(feedate,'mm')='06' then money else 0 end ) 六月,sum (case when to_char(feedate,'mm')='07' then money else 0 end ) 七月,sum (case when to_char(feedate,'mm')='08' then money else 0 end ) 八月,sum (case when to_char(feedate,'mm')='09' then money else 0 end ) 九月,sum (case when to_char(feedate,'mm')='10' then money else 0 end ) 十月,sum (case when to_char(feedate,'mm')='11' then money else 0 end ) 十一月,sum (case when to_char(feedate,'mm')='12' then money else 0 end ) 十二月 from T_ACCOUNT where to_char(feedate,'yyyy')='2013'*8.統計用水量,收費金額(分類型統計)*
根據業主類型分別統計每種居民的用水量(整數,四舍五入)及收費金額 ,如果該類型在臺賬表中無數據也需要列出值為0的記錄 , 效果如下:
語句:
select ow.name, nvl(round(sum(usenum)/1000),0) "用水量(噸)",nvl(sum(money),0) 金額 from T_OWNERTYPE ow,T_ACCOUNT ac where ow.id = ac.ownertype(+) group by ow.name分析:這里所用到的知識點包括左外連接、sum()、分組group by 、round() 和nvl()
9、統計每個區域的業主戶數,并列出合計
語句:
select ar.name 區域,count(ow.id) 業主戶數 from T_AREA ar,T_OWNERS ow,T_ADDRESS ad where ad.id=ow.addressid and ad.areaid=ar.id group by ar.name union all select '合計',count(1) from T_OWNERS10.統計每個區域的業主戶數,如果該區域沒有業主也要列出0
如圖:
語句:
select ar.name 區域,count(owad.id) 業主戶數 from T_AREA ar , ( select ow.id,ow.name,ad.areaid from T_OWNERS ow,T_ADDRESS ad where ow.addressid=ad.id ) owad where ar.id=owad.areaid(+) group by ar.name第九章 總結
1. 知識點總結
2. 上機任務
*1.表結構分析*
*Scott********用戶案例下表分析*
雇員表:EMP
部門表:Dept
工資等級表:Salgrade
獎金表:Bonus
****2.練習題
****
1.請從表EMP中查找工種是職員CLERK或經理MANAGER的雇員姓名、工資。
2.請在EMP表中查找部門號在10-30之間的雇員的姓名、部門號、工資、工作。
3.請從表EMP中查找姓名以J開頭所有雇員的姓名、工資、職位。
4.請從表EMP中查找工資低于2000的雇員的姓名、工作、工資,并按工資降序排列。
5.請從表中查詢工作是CLERK的所有人的姓名、工資、部門號、部門名稱以及部門地址的信息。
6.在表EMP中查詢所有工資高于JONES的所有雇員姓名、工作和工資。
7.列出沒有對應部門表信息的所有雇員的姓名、工作以及部門號。
8.查找工資在1000~3000之間的雇員所在部門的所有人員信息
9.雇員中誰的工資最高。
10.查詢所有雇員的姓名、SAL與COMM之和。
11.查詢所有1981年7月1日以前來的員工姓名、工資、所屬部門的名字
12.查詢各部門中1981年1月1日以后來的員工數
13.查詢所有在CHICAGO工作的經理MANAGER和銷售員SALESMAN的姓名、工資
14.查詢列出來公司就職時間超過24年的員工名單
15.查詢于1981年來公司所有員工的總收入(SAL和COMM)
16.查詢顯示每個雇員加入公司的準確時間,按××××年××月××日 時分秒顯示。
17.查詢公司中按年份月份統計各地的錄用職工數量
18.查詢列出各部門的部門名和部門經理名字
19.查詢部門平均工資最高的部門名稱和最低的部門名稱
20.查詢與雇員號為7521員工的最接近的在其后進入公司的員工姓名及其所在部門名
第十章 相關問題匯總及解答
1、在執行select trunc(sysdate,‘ss’) from dual語句時,發生以下錯誤
解答:ORACLE中的sysdate是獲取當前系統的年月日時分秒(僅精確到秒)。
2、全字段掃描查詢和指定字段掃描查詢的區別?
解答:在執行以上SQL查詢語句時,會先去數據庫中找到t_owners表,在數據表確定后,語句中"*"表示是所有字段,此時會去掃描t_owners表所有的字段。
在掃描所有字段后,會把全部字段代替"*",繼續執行查詢
而指定字段查詢,省去了掃描數據表中所有字段這一步驟,效率上有所提升。
3、關于translate函數
select translate(‘zha12#3sa4’, ‘#1234’, ‘@’) from dual;
– 對比replace
– replace 字符串級別的替換
select replace(‘accd’,‘cd’,‘ef’) from dual; --結果為: acef
– translate 字符級別的替換
select translate(‘acdd’,‘cd’,‘ef’) from dual; --結果為:aeff
–語法:translate(expr,from_string,to_string)
–示例1:將數字全部轉換為 9,其他的大寫字母轉換為 #
select translate(‘123ITCAST789’,
? ‘0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ’,
? ‘9999999999##########################’)
from dual;
–示例2:只保留數字,其它字母移除。
select translate(‘123ITCAST789’,
? ‘0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ’,
? ‘0123456789’)
from dual;
–示例3:把中文替換為英文(是按字符處理。當from_string比to_string字符少時,不會異常。在to_string中多余的字符不處理)
select translate(‘我是中國人,我愛中國’, ‘中國人’, ‘China’) from dual;
–示例4:把英文替換為中文(按字符處理。當from_string比to_string字符多時,from_string中多余的字符被移除)
select translate(‘I am Chinese, I love China’, ‘China’, ‘中國’) from dual;
–示例5:
select translate(‘中國人’, substr(‘中國人’,1,length(‘中國人’) - 1), rpad(’’,length(‘中國人’),’’)) from dual;
rpad(‘tech’, 7); 將返回’tech ’
rpad(‘tech’, 2); 將返回’te’
rpad(‘tech’, 8, ‘0’); 將返回’tech0000’
第十一章 面試題
**面試****題:**請刪除MYDEPT表中的重復記錄 (利用ROWID)
在開發過程中,由于開發人員更換,會造數據存在大量的測試數據,測試數據會存在重復的問題
[分析:
發現數據行號不同,早期插入的數據比較小
發現數據存在重復
]
delete from dept where not rowid in(
select min(rowid) from dept group by dname,loc);
總結
以上是生活随笔為你收集整理的oracle基础语法(二)ORACLE查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [css] 如何做图片预览,如何放大一个
- 下一篇: 音视频即时通讯开发平台