Oracle Sql 胡乱记
/Oracle查詢優(yōu)化改寫(xiě)/
--1、coalesce 返回多個(gè)值中,第一個(gè)不為空的值
select coalesce('', '', 's') from dual;
--2、order by
-----dbms_random.value 生產(chǎn)隨機(jī)數(shù),利用隨機(jī)數(shù)對(duì)查詢結(jié)果進(jìn)行隨機(jī)排序
select * from emp order by dbms_random.value;
--指定查詢結(jié)果中的一列進(jìn)行排序
select * from emp order by 4;
-----order by 中認(rèn)為null是最大所以null會(huì)排在第一或者最后一個(gè)
-----可以利用 nulls first 或者 nulls last 對(duì)null進(jìn)行排序處理
select * from emp order by comm nulls first;
select * from emp order by comm nulls last;
----- 多列排序,job 降序排列,如果工作一樣,按照工號(hào)升序排列
select * from emp order by job desc, empno asc;
------依次按照job,empno降序排序
select * from emp order by job, empno desc;
------將empno = 7934 的排在第一位,其余的按照empno將序排列
------ORDER BY DECODE 按照自定義的順序排序,如果沒(méi)有
------定義則按照原始值排序 case when then else end 也是同樣的道理
select * from emp order by decode(empno, 7934, 2, 1) asc;
--先按照打的分組排序,然后在分組內(nèi)按照字段排序
select empno, ename, sal
from emp
order by case
when sal <= 5000 and sal >= 3000 then
0
when sal < 3000 and sal > 1000 then
1
when sal < 1000 then
2
else
3
end asc,
3 asc;
--2
select empno,
ename,
case
when sal <= 5000 and sal >= 3000 then
0
when sal < 3000 and sal > 1000 then
1
when sal < 1000 then
2
else
3
end,
sal
from emp
order by 2 asc, 3 asc;
--3、_ 通配符,代替一個(gè)字符。
select T.*, T.ROWID from emp T where t.ename like '_EN%';
---可以通過(guò),將_表示為一個(gè)普通的字符,倆種寫(xiě)法
select T.*, T.ROWID from emp T where t.ename like '_EN%' ESCAPE '';
--4、tanslate
-----對(duì)應(yīng)字符一一替換,每一個(gè)字符的替換相當(dāng)于執(zhí)行一次REPLACE('C','1')
-----會(huì)將job字段中的C全部替換為1
select translate(job, 'CRK', '123') from emp t where t.job = 'CLERK';
---第二個(gè)字段為空的時(shí)候返回null
select translate(job, 'CRK', '') from emp t where t.job = 'CLERK';
---可以利用這個(gè)函數(shù),刪除字段的部分字符,對(duì)應(yīng)位置字符為空
select translate(job, '1CRK', '1') from emp t where t.job = 'CLERK';
--5、內(nèi)連接、左連接、右連接、外連接
--SQL-92標(biāo)準(zhǔn)寫(xiě)法,不建議用Oracle特有的= + 來(lái)表示連接
--inner join on left join on right join on outer join on
---左右連接的時(shí)候,只過(guò)濾左邊或者右邊的數(shù)據(jù),用左連接作為例子
select a.empno, a.job, a.comm, b.empno, b.job, b.comm
from emp a
left join emp2 b
on (a.empno = b.empno and b.comm is not null);
select a.empno, a.job, a.comm, b.empno, b.job, b.comm
from emp a, emp2 b
where a.empno = b.empno(+)
and b.comm(+) is not null;
--6、in 多列寫(xiě)法
select *
from emp t
where (t.empno, t.ename) in (select t2.empno, t2.ename from emp t2);
---not in 注意事項(xiàng):如果在子查詢結(jié)果中包含null,not in 則返回null
select * from emp t where t.mgr not in (select mgr from emp2);
-- 7、insert into 如果表中有默認(rèn)字段嗎,那么不能顯示的插入null,否則表中的字段值
---不會(huì)是默認(rèn)值,依然是null
---8、形成數(shù)據(jù)結(jié)構(gòu)
---level 代表總共有幾層樹(shù)形結(jié)構(gòu)
select level from dual connect by level;
---9、正則表達(dá)式(沒(méi)必要記住,了解規(guī)則和用途就可以了)
---regexp_count 統(tǒng)計(jì)匹配的
---regexp_replace 替換匹配的
---regexp_like 用正則表達(dá)式模糊查詢
select regexp_count('abc,bcd,ddd,4434', ',') from dual;
select regexp_replace('abc,bcd,ddd,4434', ',') from dual;
---X 報(bào)表分析精華--Oracle分析函數(shù)
--listagg(x,',') within group (order by x)
--將某個(gè)字段的多列用逗號(hào)(,)連接起來(lái)
--同樣的方法有wm_concat,但是
select job, listagg(ename, ',') within group(order by ename asc)
from emp
group by job;
---10、instr 字符串位置查找函數(shù)
--- 查找分割符的位置,然后截取
--- 從第一個(gè)字符開(kāi)始,檢索第二次出現(xiàn)的位置
select instr('zzz,xxx,tt', ',', '1', '2') from dual;
---11、count(*) 當(dāng)表中沒(méi)有數(shù)據(jù)時(shí)返回一條數(shù)據(jù)值為0,當(dāng)有g(shù)roup by 的時(shí)候 沒(méi)有數(shù)據(jù)返回
---12、 sum() over (order by x) 按順序累加
---(如果需要計(jì)算累計(jì)差,可以將數(shù)字轉(zhuǎn)換為負(fù)數(shù),然后計(jì)算累積和)
select ENAME, SAL, SUM(SAL) OVER(ORDER BY EMPNO) from emp;
---13、分析函數(shù)
----按照分組排序獲取第一個(gè)值或者最后一個(gè)值
---- max(ename) keep(dense_rank first order by sal desc) over()
select empno,
ename,
sal,
max(ename) keep(dense_rank first order by sal desc) over(),
max(sal) keep(dense_rank first order by sal desc) over(),
max(ename) keep(dense_rank last order by sal desc) over()
from emp;
---獲取分組的最后一個(gè)值
select deptno,
max(ename) keep(dense_rank last order by sal desc),
max(sal) keep(dense_rank last order by sal desc),
max(ename) keep(dense_rank last order by sal desc)
from emp group by deptno;
---- lead 獲取當(dāng)前行下一行的數(shù)據(jù), lag獲取當(dāng)前行上一行的數(shù)據(jù)
select ename,
sal,
lead(sal) over(order by sal),
lag(sal) over(order by sal)
from emp
order by sal;
----14、extract 函數(shù)返回值為數(shù)字,獲取時(shí)間字段的某一個(gè)值
select extract(day from sysdate) from dual;
---- to_char(sysdate,'xxx') d day 1 ww iw ...
---- next_day 1234567 下一個(gè) 1 代表周天 2代表周一。。。>
select to_char(sysdate, 'day') from dual;
select next_day(sysdate, 1) from dual;
--月歷
select max((case dd
when 2 then
d
end)) d1
from (select to_char(dt, 'iw') weak,
to_char(dt, 'dd') d,
to_number(to_char(dt, 'd')) dd
from (select (trunc(sysdate, 'mm') + level - 1) dt
from dual
connect by level <= 30))
group by weak
order by weak
--rows between 分析函數(shù)開(kāi)窗 (按行)
--range between 按照范圍開(kāi)窗(針對(duì)數(shù)字和日期列)
select sum(sal) over(order by empno rows between unbounded preceding and 1 preceding)
from emp;
-----15 求余數(shù)函數(shù)
select mod(34, 4) from dual;
-----16 分頁(yè)常用偽列 rownum
----- 16.1 先排序,在獲取rownum取值
----- 16.2 獲取rownum的值后才能按照分頁(yè)過(guò)濾
-----17 SQL動(dòng)態(tài)分割字符串
----- 知道分隔符,但每一個(gè)都可能包含多個(gè)分割符
---- 針對(duì)的是一行數(shù)據(jù)的結(jié)果,
---- level 樹(shù)形結(jié)構(gòu)查詢結(jié)構(gòu)
select regexp_substr(l, '[^,]+', 1, level)
from test6
where id = 1
connect by level <= regexp_count(l, ',');
----18、行轉(zhuǎn)列 pivot 等價(jià)與 case when
----帶有聚合函數(shù)的時(shí)候,不要使用倆次或倆次以上的pivot
select *
from (select job, ename, deptno from emp) pivot(count(ename) as c for deptno in(10 as d10,
20 as d20,
30 as d30));
select *
from (select deptno, ename, job from emp) pivot(count(ename) as c for job in('CLERK' as
job_clark,
'SALESMAN' as
job_SALESMAN,
'MANAGER' as
job_MANAGER,
'ANALYST' as
job_ANALYST,
'PRESIDENT' as
job_PRESIDENT));
----19、列轉(zhuǎn)行 unpivot (同樣的需求可以用 union all 處理),要保證轉(zhuǎn)換的列有同樣的
----數(shù)據(jù)類型
-----unpivot include unlls 包含空值
select
from (select
from (select job, ename, deptno from emp) pivot(count(ename) as c for deptno in(10 as d10,
20 as d20,
30 as d30))) unpivot(sal for deptno in(d10_c,
d20_c,
--包含null值 d30_c));
select * from emp unpivot INCLUDE NULLS(salZE for lie in(SAL, COMM));
----20、ceil(rn/5) 返回大于或等于表達(dá)式的最小整數(shù)
---- ceil 按照5個(gè)一組編號(hào),然后在組內(nèi)排序加序號(hào)
---- 然后用序號(hào)進(jìn)行行轉(zhuǎn)列
select *
from (select gp,
ename,
row_number() over(partition by gp order by ename) xh
from (select ceil(rn / 5) gp, ename
from (select rownum rn, ename
from (select ename from emp order by ename)))) pivot(max(ename) as x for xh in(1 as e1,
2 as e2,
----21 ntile(3) over 多數(shù)據(jù)進(jìn)行分組,3為分組約定
select ntile(3) over(order by empno),empno,ename from emp where job in ('CLERK', 'MANAGER')
----22 rollup 求統(tǒng)計(jì)列的合計(jì)值
---- grouping(deptno) 該列被匯總的時(shí)候 返回值為1 ,否則返回0
---- 處理分組字段存在空的情況下,與合計(jì)行無(wú)法區(qū)分
select deptno,sum(sal) from emp group by rollup (deptno)
-- emp 按照 deptno, job, empno 分組,同時(shí)計(jì)算出 deptno, job, empno 的合計(jì)、deptno, job的合計(jì)
-- deptno 的合計(jì)
--grouping 用來(lái)區(qū)分合計(jì)列
select deptno, job, empno, sum(sal), grouping(deptno), grouping(job),grouping(empno)
from emp
group by rollup(deptno, job, empno);
--cube 按照 deptno, job, empno 各種可能組合計(jì)算合計(jì),最后加一行總計(jì)
--grouping_id deptno,job,empno 三種可能組合合計(jì)的分類ID
select deptno, job, empno, sum(sal), grouping_id(deptno,job,empno)
from emp
group by cube(deptno, job, empno);
select deptno,
job,
sum(sal),
grouping_id(deptno, job),
case grouping_id(deptno, job)
when 0 then
'按照部門和工作分組'
when 1 then
'按照部分分組'
when 2 then
'按照工作分組'
when 3 then
'總合計(jì)'
end fl
from emp
where emp.deptno is not null
and emp.job is not null
group by cube(deptno, job);
----23 lpad rpad 左右補(bǔ)齊位數(shù)
----第二個(gè)參數(shù)代表字符串
----第二個(gè)參數(shù)代表期望的長(zhǎng)度,不足補(bǔ)齊,超過(guò)截取
----第三個(gè)參數(shù)代表如果字符串長(zhǎng)度不夠則用這個(gè)補(bǔ)齊
select rpad(1,2,',') from dual;
select lpad(1,2,',') from dual;
----24 九九乘法表
with x as(
select level lv from dual connect by level <=9)
, xx as(
select x1.lv lv_a,x2.lv lv_b, to_char(x1.lv) || ' * ' ||
to_char(x2.lv) || ' = ' || to_char(x1.lv * x2.lv) c from x x1,x x2 where x1.lv <= x2.lv)
select lv_b,listagg(c,' ') within group(order by lv_b) from xx group by lv_b; 3 as e3,
4 as e4,
-----25 遞歸查詢
----(PRIOR ename) 獲取上一級(jí)的信息,可以獲取所有列的信息
---- PRIOR 指定按照哪一個(gè)字段進(jìn)行遞歸
---- connect by PRIOR emp.empno = emp.mgr 找出與本級(jí)empno 相等的mgr數(shù)據(jù),向下遞歸
---- connect by emp.empno = PRIOR emp.mgr 找出與本級(jí)mgr 相等的empno數(shù)據(jù),向上遞歸
select empno, ename,mgr,(PRIOR ename)
from emp
start with empno = '7902'
connect by PRIOR emp.empno = emp.mgr;
--偽列
--level 層級(jí)編碼
--connect_by_isleaf 葉子節(jié)點(diǎn)標(biāo)識(shí)
select empno, ename,mgr,(PRIOR job),level,connect_by_isleaf
from emp
start with empno = '7902'
connect by PRIOR emp.empno = emp.mgr;
---sys_connect_by_path 可以將層級(jí)中的部分字段連接起來(lái)(按照層級(jí)連接)
--- 3、2、1 連接;2、1連接;1連接
select empno,
ename,
mgr,
(PRIOR job),
level,
connect_by_isleaf,
sys_connect_by_path(ename, ',')
from emp
start with empno = '7902'
connect by emp.empno = PRIOR emp.mgr;
--- order siblings by 樹(shù)形分支,分別排序,不按照整體結(jié)構(gòu)排序
---無(wú)法看清層級(jí)結(jié)構(gòu)
select empno, ename,mgr,(PRIOR job),level,connect_by_isleaf
from emp
start with empno = '7566'
connect by PRIOR emp.empno = emp.mgr
order siblings by empno;
--- 樹(shù)形查詢中 where 字段過(guò)濾的是查詢結(jié)果,
--- 所以如果需要樹(shù)形查詢部分?jǐn)?shù)據(jù),必須先過(guò)濾,然后作為子查詢結(jié)構(gòu)
--- 進(jìn)行樹(shù)形查詢
select
from (select from emp where deptno = '20')
start with mgr is null
connect by prior empno = mgr;
--如果要過(guò)濾一個(gè)完整的分支
--需要在connect by prior 后加入過(guò)濾語(yǔ)句
--不能在where中加入
select *
from emp
start with mgr is null
connect by prior empno = mgr
and empno !='7566';
----26、取各個(gè)分組的 最大最小 第一行 最后一行
select job,
first_value(ename) over(partition by job order by sal desc),
max(ename) keep(dense_rank first order by sal desc) over(partition by job),
last_value(ename) over(partition by job order by sal desc),
max(ename) keep(dense_rank last order by sal desc) over(partition by job)
from emp;
Oracle 在執(zhí)行SQL語(yǔ)句時(shí),有兩種優(yōu)化方法:即基于規(guī)則的RBO和基于代價(jià)的CBO。 在SQL執(zhí)教的時(shí)候,到底采用何種優(yōu)化方法,就由Oracle參數(shù) optimizer_mode 來(lái)決定。
SQL> show parameter optimizer_mode
PL/SQL F5 根據(jù)不同的選擇應(yīng)用不同的優(yōu)化方法
轉(zhuǎn)載于:https://www.cnblogs.com/zhouxiangting/p/10784583.html
總結(jié)
以上是生活随笔為你收集整理的Oracle Sql 胡乱记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 梦到放风筝是什么意思
- 下一篇: leetcode 113. 路径总和 I