日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

只是简单读了读《oracle查询优化改写》,就让我获益匪浅,想写好sql,这一本书就够了!

發布時間:2025/3/19 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 只是简单读了读《oracle查询优化改写》,就让我获益匪浅,想写好sql,这一本书就够了! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

寫在前面

基礎知識

空值

返回前幾行

獲取隨機數

like

排序

union

分頁(6-10條)

表關聯

復制表

日期

日期加減

trunc對于日期的用法

獲取時間

判斷是否是閏年(只需要判斷二月底是哪一天):

數字

聚集函數使用前先把null轉化為0:coalesce(a,0)

ROUND(number[,decimals])

trunc對數字的操作(取整)

其他取大小值

字符串

原樣輸出字符串Q-quote:? q'[內容]'

計算str中逗號出現的次數

字符串中字符替換

正則表達式

實例

相關函數

求余數

返回第一個不是空的值

Case具有兩種格式。簡單Case函數和Case搜索函數。

translate函數

lag與lead函數

書中還有很多知識點需要去挖掘!


寫在前面

前些日子寫sql語句,因為之前寫sql僅僅局限于簡單的增刪改查,碰到復雜難寫的sql就得冥思苦想,真正意義上的面向百度編程。

簡單讀了《oracle查詢優化改寫》,真的是讓我豁然開朗,非常建議新人朋友、甚至想要提高自己的技術高人,都有時間來讀一讀。

sql語法僅限oracle!!!

基礎知識

空值

篩選條件只能是 is null 或者is not null。

null不支持加減乘除大小相等比較,否則只能為空。

order by 3 nulls first -----------空值排在前

order by 3 nulls lase ------------空值排在后

返回前幾行

返回前2行(如果要用=號,只能再加一層并且加上rownum進行篩選) : where rownum<=2

rownum可以在sql語句后面直接where!!

獲取隨機數

dbms_random.value

dbms_random.value可以在sql語句后面直接order by!!

like

like '%e_' ------%代表一個或多個字符,_代表一個字符。

like '\_abc%'? escape'\' -------轉義字符\就可以匹配出_abc,escape定義轉義字符。

like '\\abc%' ------就可以匹配出\abc。

排序

asc 、 desc? ?升序 降序

order by 3 ----按第三列排序,這種排序可以不用使用字段!!也不用再加一層

order by 3 nulls first -----------空值排在前

order by 3 nulls lase ------------空值排在后

order by 可以直接跟case when 函數,(相當于把這一列提取出來到order by里面了,而不用在列中顯示)

union

union是求兩個(或者多個)集合的并集(不允許重復元素),得到的集合是{1,2,3,4,5,6,7,8,9};

union all也是求兩個(或者多個)集合的并集(允許重復元素),得到的集合是{1,2,3,4,5,5,6,7,8,9};

而minus是求兩個集合的差集,并且是前面一個集合去掉重復元素的部分,得到的集合是{1,2,3,4};

分頁(6-10條)

根據rownum,先獲取前10條,再在最外層獲取6-10條。

表關聯

1、select * from A where id in (select id from B)--使用in

2、select * from A where exists(select B.id from B where B.id=A.id)--使用exists

也可以完全不使用in和exists(這種相當于inner join!):

3、select A.* from A,B where A.id=B.id--不使用in和exists

還有not in、not exists表示相反的意思。

left join?

right join?

full join

inner join?

復制表

create table test2 as select * from test;

只復制表的定義:

create table test2 as select * from test where 1=2;

多表插入(當使用了ALL時,每一個WHEN子句都會進行判斷;使用FIRST,FIRST則是按順序判斷WHEN子句,只執行第一個滿足條件的WHEN子句,后面的WHEN子句則直接被跳過):

INSERT ALL

WHEN sum_orders < 10000 THEN INTO small_customers

WHEN sum_orders >= 10000 AND sum_orders < 100000 THEN INTO medium_customers

ELSE INTO lager_customers

SELECT customer_id, SUM(order_total) sum_orders

FROM oe.orders

GROUP BY customer_id;

日期

日期加減

在oracle中,date類型直接相減得相差天數,加減數字就是加減天數,加減月份要用add_months函數: hiredate - 5 -------減五天 hiredate + 5 -------加五天 add_months(hiredate,-5) ------減五個月 add_months(hiredate,5) ------加五個月 add_months(hiredate,-5*12) ------減五年 add_months(hiredate,5*12) ------加五年 hiredate - 5/24/60/60 -----減五秒 hiredate + 5/24/60/60 -----加五秒 hiredate - 5/24/60 -----減五分鐘 hiredate + 5/24/60 -----加五分鐘 hiredate - 5/24 -----減五小時 hiredate + 5/24 -----加五小時date1 - date2 ----------------間隔天數 (date1 -date2)*24 --------------間隔小時數 (date1 -date2)*24*60 --------------間隔分鐘數 (date1 -date2)*24*60*60 --------------間隔秒數 months_between(date1,date2)------間隔月 months_between(date1,date2)/12---------間隔年

trunc對于日期的用法

select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),to_char(trunc(sysdate), 'yyyy-mm-dd hh24:mi:ss')from dual t;--sysdate和trunc(sysdate)是不一樣的 sysdate在當天的零時零分零秒等于trunc(sysdate) select trunc(sysdate, 'dd'), trunc(sysdate) from dual t; --今天 20140703 零時零分零秒 select to_char(trunc(sysdate, 'dd'), 'yyyy/mm/dd hh24:mi:ss'),to_char(trunc(sysdate), 'yyyy/mm/dd hh24:mi:ss')from dual;select trunc(sysdate-to_date('20140709 23:12:12','yyyy/mm/dd hh24:mi:ss')) from dual t;--兩個日期相差的天數 select trunc(sysdate-1) from dual t;--昨天 select trunc(sysdate+1) from dual t;--明天 select trunc(sysdate, 'yy') from dual;--當年第一天 select trunc(sysdate, 'year') from dual;--當年第一天 select trunc(sysdate, 'yyyy') from dual;--當年第一天 select trunc(sysdate, 'q') from dual;--當前時間所在的季度的第一天 select trunc(sysdate, 'mm') from dual;--當月第一天 select trunc(sysdate, 'month') from dual;--當月第一天 select trunc(sysdate, 'd') from dual;--返回本周的第一天(周日為第一天) select trunc(sysdate,'day') from dual;--返回本周的第一天(周日為第一天) select trunc(sysdate, 'iw') from dual;--本周第二天(周日為第一天) select trunc(sysdate, 'hh') from dual; --當前時間,精確到小時 select trunc(sysdate, 'hh24') from dual;--當前時間。精確到小時 select trunc(sysdate, 'mi') from dual;--當前時間。精確到分鐘 沒有精確到秒的精度

獲取時間

to_number(to_char(date1,'hh24'))-----時 to_number(to_char(date1,'mi'))-----分 to_number(to_char(date1,'ss'))-----秒 to_number(to_char(date1,'dd'))-----日 to_number(to_char(date1,'mm'))-----月 to_number(to_char(date1,'yyyy'))-----年 to_number(to_char(date1,'ddd'))-----年內第幾天 trunc(date1,'dd')----一天之始 trunc(date1,'day')----周初 trunc(date1,'mm')----月初 last_day(date1)-----月末 add_months(trunc(date1,'mm'),1)---下月初 trunc(date1,'yy')-----年初 to_char(date1,'day')----周幾 to_char(date1,'month')----月份 next_day(date1,1) ---- 下個周日獲取時間(to_char獲取的是字符串,extract獲取的是數字類型): extract(YEARfrom date1)--------年 extract(MONTH from date1)--------月 extract(DAY from date1)--------日 extract(HOUR from date1)--------小時 extract(MINUTE from date1)--------分鐘 extract(SECOND from date1)--------秒

判斷是否是閏年(只需要判斷二月底是哪一天):

last_day(add_months(trunc(hiredate,'y'),1)) as 二月底

數字

聚集函數使用前先把null轉化為0:coalesce(a,0)

avg(a) ----平均值

min(a) -------最小值

max(a) ------ 最大值

sum(a) ------總數

count(*) -----總行數

sum(a) over(order by b) ----從第一行到當前行的總和,(先根據b排序之后)

ROUND(number[,decimals])

四舍五入,decimals為可選值,表示小數點后的位數。可為負數!

trunc對數字的操作(取整)

/* TRUNC(number,num_digits) Number 須要截尾取整的數字。 Num_digits 用于指定取整精度的數字。 Num_digits 的默認值為 0。 正數向后截取,負數向前截取 TRUNC()函數截取時不進行四舍五入 */ select trunc(123.458) from dual; --123 select trunc(123.458, 0) from dual; --123 select trunc(123.458, 1) from dual; --123.4 select trunc(123.458, -1) from dual; --120 select trunc(123.458, -4) from dual; --0 select trunc(123.458, 4) from dual; --123.458 select trunc(123) from dual; --123 select trunc(123, 1) from dual; --123 select trunc(123, -1) from dual; --120

其他取大小值

min(sal) over(partition by deptno) 部門最低工資, max(sal) over(partition by deptno) 部門最高工資lead(sal, 1, 0) over(partition by deptno order by sal) 比自己工資高的部門前一個, lag(sal, 1, 0) over(partition by deptno order by sal) 比自己工資低的部門后一個, nvl(lead(sal) over(partition by deptno order by sal) - sal, 0) 比自己工資高的部門前一個差額, nvl(sal - lag(sal) over(partition by deptno order by sal), 0) 比自己工資高的部門后一個差額取最大值最小值也可以用: first_value(a) over(partition by deptno) last_value(a) over(partition by deptno)

字符串

substr(a,1,2)--------截取a字符串的從第1個開始數2個字符。

lower('A') --------字符串替換成小寫

listagg(a,',') within group(order by b)-----用在group by中,多個列用逗號間隔顯示

原樣輸出字符串Q-quote:? q'[內容]'

SELECT Q'[I'm a boy,my name is 'david']' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'(I'm a boy,my name is 'david')' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'{I'm a boy,my name is 'david'}' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'|I'm a boy,my name is 'david'|' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'aI'm a boy,my name is 'david'a' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'2I'm a boy,my name is 'david'2' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'@I'm a boy,my name is 'david'@' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'*I'm a boy,my name is 'david'*' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'#I'm a boy,my name is 'david'#' FROM DUAL; --結果:I'm a boy,my name is 'david' SELECT Q'[[@#$%^&*~?/" ']]' FROM DUAL; --結果:[@#$%^&*~?/" ']

計算str中逗號出現的次數

regexp_count(str,',')-------計算str中逗號出現的次數

字符串中字符替換

replace(str_source,str1,str2)??把 str_source 中 str1 字符串替換為 str2 字符串,當 str2 為 null 或'' 時,把str_source 中的 str1 字符串剔除

replace(str_source,str1)?????????把str_source 中的 str1 字符串剔除

regexp_replace(str_source,pattern_str,rep_str) 支持正則表達式,用法類似于 replace,但功能更強大

regexp_replace(str_source,pattern_str)???把 str_source 中的 pattern_str 字符串剔除

translate(str_source,chr1,chr2) 以字符為單位,把 str_source 中的 chr1 字符對應替換為 chr2。如果 chr1 比chr2 長,那么在 chr1 中而不在 chr2 中的字符將被剔除,因為沒有對應的替換字符。需注意 chr2 不能為 null 或'',否則返回值也為空 (translate(str,'1abc','1')---去除abc)

比方:

select REGEXP_SUBSTR(‘虹橋/北京’,’[^/]+’,1,1) from dual -----返回的是虹橋

select REGEXP_SUBSTR(‘虹橋/北京’,’[^/]+’,1,2) from dual----------返回的是北京

第一個參數是要解析的字符串,第二個是正在表達式,第三個表示字符串解析時的起始位置。比方:

select REGEXP_SUBSTR(‘虹橋/北京’,’[^/]+’,2,1) from dual------返回的是橋

第四個參數表示取拆分后數組里的第幾個值。

正則表達式

ORACLE中的支持正則表達式的函數主要有下面四個:

1,REGEXP_LIKE :與LIKE的功能相似

2,REGEXP_INSTR :與INSTR的功能相似

3,REGEXP_SUBSTR :與SUBSTR的功能相似

4,REGEXP_REPLACE :與REPLACE的功能相似

5,REGEXP_COUNT? :?regexp_count(str,',')-------計算str中逗號出現的次數

它們在用法上與Oracle SQL 函數LIKE、INSTR、SUBSTR 和REPLACE 用法相同,

但是它們使用POSIX 正則表達式代替了老的百分號(%)和通配符(_)字符。

POSIX 正則表達式由標準的元字符(metacharacters)所構成:

'^' 匹配輸入字符串的開始位置,在方括號表達式中使用,此時它表示不接受該字符集合。

'$' 匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹

配 '/n' 或 '/r'。

'.' 匹配除換行符之外的任何單字符。

'?' 匹配前面的子表達式零次或一次。

'+' 匹配前面的子表達式一次或多次。

'*' 匹配前面的子表達式零次或多次。

'|' 指明兩項之間的一個選擇。例子'^([a-z]+|[0-9]+)$'表示所有小寫字母或數字組合成的

字符串。

'( )' 標記一個子表達式的開始和結束位置。

'[]' 標記一個中括號表達式。

'{m,n}' 一個精確地出現次數范圍,m=<出現次數<=n,'{m}'表示出現m次,'{m,}'表示至少

出現m次。

/num 匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。

字符簇:

[[:alpha:]] 任何字母。

[[:digit:]] 任何數字。

[[:alnum:]] 任何字母和數字。

[[:space:]] 任何白字符。

[[:upper:]] 任何大寫字母。

[[:lower:]] 任何小寫字母。

[[:punct:]] 任何標點符號。

[[:xdigit:]] 任何16進制的數字,相當于[0-9a-fA-F]。

各種操作符的運算優先級

/轉義符

(), (?:), (?=), [] 圓括號和方括號

*, +, ?, {n}, {n,}, {n,m} 限定符

^, $, anymetacharacter 位置和順序

*/

實例

--創建表

create table fzq

(

id varchar(4),

value varchar(10)

);

--數據插入

insert into fzq values

('1','1234560');

insert into fzq values

('2','1234560');

insert into fzq values

('3','1b3b560');

insert into fzq values

('4','abc');

insert into fzq values

('5','abcde');

insert into fzq values

('6','ADREasx');

insert into fzq values

('7','123 45');

insert into fzq values

('8','adc de');

insert into fzq values

('9','adc,.de');

insert into fzq values

('10','1B');

insert into fzq values

('10','abcbvbnb');

insert into fzq values

('11','11114560');

insert into fzq values

('11','11124560');

--regexp_like

--查詢value中以1開頭60結束的記錄并且長度是7位

select * from fzq where value like '1____60';

select * from fzq where regexp_like(value,'1....60');

--查詢value中以1開頭60結束的記錄并且長度是7位并且全部是數字的記錄。

--使用like就不是很好實現了。

select * from fzq where regexp_like(value,'1[0-9]{4}60');

-- 也可以這樣實現,使用字符集。

select * from fzq where regexp_like(value,'1[[:digit:]]{4}60');

-- 查詢value中不是純數字的記錄

select * from fzq where not regexp_like(value,'^[[:digit:]]+$');

-- 查詢value中不包含任何數字的記錄。

select * from fzq where regexp_like(value,'^[^[:digit:]]+$');

--查詢以12或者1b開頭的記錄.不區分大小寫。

select * from fzq where regexp_like(value,'^1[2b]','i');

--查詢以12或者1b開頭的記錄.區分大小寫。

select * from fzq where regexp_like(value,'^1[2B]');

-- 查詢數據中包含空白的記錄。

select * from fzq where regexp_like(value,'[[:space:]]');

--查詢所有包含小寫字母或者數字的記錄。

select * from fzq where regexp_like(value,'^([a-z]+|[0-9]+)$');

--查詢任何包含標點符號的記錄。

select * from fzq where regexp_like(value,'[[:punct:]]');

相關函數

求余數

mod(a,2)---求余數

返回第一個不是空的值

只能寫兩個參數: nvl(a,b)

可以寫多個參數 : coalesce(a,b,c,d)

Case具有兩種格式。簡單Case函數和Case搜索函數。

--簡單Case函數??

CASE sex??

WHEN '1' THEN '男'??

WHEN '2' THEN '女'??

ELSE '其他' END??

--Case搜索函數??

CASE WHEN sex = '1' THEN '男'??

WHEN sex = '2' THEN '女'??

ELSE '其他' END??

translate函數

translate(a,b,c)------把a中b的內容依次替代為c的內容

translate('ab你好bcadefg','abcdefg','1234567')? ---------12你好2314567

translate(a,b,'') ----------結果為null

translate('ab你好bcadefg','1abcdefg','1')-------結果為'你好'

lag與lead函數

lag與lead函數是跟偏移量相關的兩個分析函數,通過這兩個函數可以在一次查詢中取出同一字段的前N行的數據(lag)和后N行的數據(lead)作為獨立的列,從而更方便地進行進行數據過濾。這種操作可以代替表的自聯接,并且LAG和LEAD有更高的效率。

?

over()表示 lag()與lead()操作的數據都在over()的范圍內,他里面可以使用partition by 語句(用于分組) order by 語句(用于排序)。partition by a order by b表示以a字段進行分組,再 以b字段進行排序,對數據進行查詢。

?

例如:lead(field, num, defaultvalue) field需要查找的字段,num往后查找的num行的數據,defaultvalue沒有符合條件的默認值。

書中還有很多知識點需要去挖掘!

總結

以上是生活随笔為你收集整理的只是简单读了读《oracle查询优化改写》,就让我获益匪浅,想写好sql,这一本书就够了!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。