小方的Java博客

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  27 随笔 :: 17 文章 :: 115 评论 :: 0 Trackbacks

很久以前看某本书整理的,忘了哪本了,现在贡献出来。

1)在select语句中使用条件逻辑

1select ename,sal,   
2       case when sal <= 2000 then 'UNDERPAID'  
3            when sal >= 4000 then 'OVERPAID'  
4            else 'OK'  
5       end as status   
6from emp   


ENAME SAL STATUS
---------- ---------- ---------
SMITH 800 UNDERPAID
ALLEN 1600 UNDERPAID
WARD 1250 UNDERPAID
JONES 2975 OK
MARTIN 1250 UNDERPAID
BLAKE 2850 OK
CLARK 2450 OK
SCOTT 3000 OK
KING 5000 OVERPAID
TURNER 1500 UNDERPAID
ADAMS 1100 UNDERPAID
JAMES 950 UNDERPAID

FORD 3000 OK
MILLER 1300 UNDERPAID

 

2)从表中随机返回n条记录

1select *   
2  from (   
3    select ename, job   
4    from emp   
5    order by dbms_random.value()   
6  )   
7  where rownum <= 5 

 

3)按照子串排序

比如要从EMP表中返回员工名字和职位,并且按照职位字段最后2个字符排序

1select ename,job   
2  from emp   
3order by substr(job,length(job)-2

ENAME JOB
---------- ---------
KING PRESIDENT
SMITH CLERK
ADAMS CLERK
JAMES CLERK
MILLER CLERK
JONES MANAGER
CLARK MANAGER
BLAKE MANAGER
ALLEN SALESMAN
MARTIN SALESMAN
WARD SALESMAN
TURNER SALESMAN
SCOTT ANALYST
FORD ANALYST

 

4)处理空值排序

当被排序的列存在空值,如果希望空值不影响现有排序

1select ename,sal,comm   
2   from emp   
3order by comm nulls last 

 

ENAME SAL COMM
------ ----- ---------
TURNER 1500 0
ALLEN 1600 300
WARD 1250 500
MARTIN 1250 1400
SMITH 800
JONES 2975
JAMES 950
MILLER 1300
FORD 3000
ADAMS 1100
BLAKE 2850
CLARK 2450
SCOTT 3000
KING 5000

1select ename,sal,comm   
2  from emp   
3order by comm desc nulls first 


ENAME SAL COMM
------ ----- ----------
SMITH 800
JONES 2975
CLARK 2450
BLAKE 2850
SCOTT 3000
KING 5000
JAMES 950
MILLER 1300
FORD 3000
ADAMS 1100
MARTIN 1250 1400
WARD 1250 500
ALLEN 1600 300
TURNER 1500 0

5)根据数据项的键排序

比如如果job是“SALESMAN”,根据COMM排序,否则根据SAL排序

1select ename,sal,job,comm   
2  from emp   
3 order by case when job = 'SALESMAN' then comm else sal end  


ENAME SAL JOB COMM
---------- ---------- --------- ----------
TURNER 1500 SALESMAN 0
ALLEN 1600 SALESMAN 300
WARD 1250 SALESMAN 500
SMITH 800 CLERK
JAMES 950 CLERK
ADAMS 1100 CLERK
MARTIN 1250 SALESMAN 1300
MILLER 1300 CLERK
CLARK 2450 MANAGER
BLAKE 2850 MANAGER
JONES 2975 MANAGER
SCOTT 3000 ANALYST
FORD 3000 ANALYST


 

6)从一个表中查找另一个表中没有的值

比如要从DEPT中查找在表EMP中不存在数据的所有部门(数据中,DEPTNO值为40的记录在表EMP中不存在)

1select deptno from dept   
2minus   
3select deptno from emp 


 

7)在运算和比较时使用null值

null不会等于和不等于任何值,null和自己都不等于。以下例子是当comm有null的情况下列出比“WARD”提成低的员工。 (coalesce函数将null转换为其他值)

1select ename,comm,coalesce(comm,0)   
2  from emp   
3where coalesce(comm,0< ( select comm   
4                                     from emp   
5                                    where ename = 'WARD' )


ENAME COMM COALESCE(COMM,0)
---------- ---------- ----------------
SMITH 0
ALLEN 300 300
JONES 0
BLAKE 0
CLARK 0
SCOTT 0
KING 0
TURNER 0 0
ADAMS 0
JAMES 0
FORD 0
MILLER 0

 

8)删除重复记录

对于名字重复的记录,保留一个

1delete from dupes   
2 where id not in ( select min(id)   
3                      from dupes   
4                     group by name ) 

 

9)合并记录
比如如下需求:
如果表EMP_COMMISSION中的某员工也存在于EMP表,那么更新comm为1000
如果以上员工已经更新到1000的员工,如果他们SAL少于2000,删除他们
否则,从表中提取该员工插入表EMP_COMMISSION

1merge into emp_commission ec   
2using (select * from emp) emp   
3    on (ec.empno=emp.empno)   
4 when matched then  
5       update set ec.comm = 1000   
6       delete where (sal < 2000)   
7 when not matched then  
8        insert (ec.empno,ec.ename,ec.deptno,ec.comm)   
9       values (emp.empno,emp.ename,emp.deptno,emp.comm)  

 

10)用sql生成sql

1select 'select count(*) from '||table_name||';' cnts   
2  from user_tables;   


(user_tables是oracle的元数据表之一)

CNTS
----------------------------------------
select count(*) from ANT;
select count(*) from BONUS;
select count(*) from DEMO1;
select count(*) from DEMO2;
select count(*) from DEPT;
select count(*) from DUMMY;
select count(*) from EMP;
select count(*) from EMP_SALES;
select count(*) from EMP_SCORE;
select count(*) from PROFESSOR;
select count(*) from T;
select count(*) from T1;
select count(*) from T2;
select count(*) from T3;
select count(*) from TEACH;
select count(*) from TEST;
select count(*) from TRX_LOG;
select count(*) from X;

 

11)计算字符在字符串里的出现次数

判断字符串里有多少个‘ , ’

1select (length('10,CLARK,MANAGER')-   
2  length(replace('10,CLARK,MANAGER',',','')))/length(',')   
3  as cnt   
4from t1   


先计算原字符串长度,再减去去掉逗号的长度,这个差再除以‘,’的长度

 

12)将数字和字母分离


原数据是:

DATA
---------------
SMITH800
ALLEN1600
WARD1250
JONES2975
MARTIN1250
BLAKE2850
CLARK2450
SCOTT3000
KING5000
TURNER1500
ADAMS1100
JAMES950
FORD3000
MILLER1300
 1select replace(   
 2  translate(data,'0123456789','0000000000'),'0') ename,   
 3  to_number(   
 4    replace(   
 5    translate(lower(data),   
 6      'abcdefghijklmnopqrstuvwxyz',   
 7      rpad('z',26,'z')),'z')) sal   
 8  from (   
 9    select ename||sal data from emp   
10 )   

ENAME SAL
---------- ----------
SMITH 800
ALLEN 1600
WARD 1250
JONES 2975
MARTIN 1250
BLAKE 2850
CLARK 2450
SCOTT 3000
KING 5000
TURNER 1500
ADAMS 1100
JAMES 950
FORD 3000
MILLER 1300

思路是很复杂的,比如先去除数字,是先把所有数字翻译为0,然后用replace去掉0.


 

13)根据表中的行创建分割列表


表中数据:
DEPTNO EMPS
------ ----------
10 CLARK
10 KING
10 MILLER
20 SMITH
20 ADAMS
20 FORD
20 SCOTT
20 JONES
30 ALLEN
30 BLAKE
30 MARTIN
30 JAMES
30 TURNER
30 WARD

 1select deptno,   
 2    ltrim(sys_connect_by_path(ename,','),',') emps   
 3  from (   
 4  select deptno,   
 5    ename,   
 6    row_number() over   
 7       (partition by deptno order by empno) rn,   
 8    count(*) over   
 9      (partition by deptno) cnt   
10  from emp   
11  )   
12  where level = cnt   
13  start with rn = 1   
14    connect by prior deptno = deptno and prior rn = rn-1 


查询结果
DEPTNO EMPS
------- ------------------------------------
10 CLARK,KING,MILLER
20 SMITH,JONES,SCOTT,ADAMS,FORD
30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

 

14)按字母顺序排序

 1select old_name, new_name   
 2  from (select old_name, replace(sys_connect_by_path(c, ' '), ' ') new_name   
 3          from (select e.ename old_name,   
 4                       row_number() over(partition by e.ename order by substr(e.ename, iter.pos, 1)) rn,   
 5                       substr(e.ename, iter.pos, 1) c   
 6                  from emp e, (select rownum pos from emp) iter   
 7                 where iter.pos <= length(e.ename)   
 8                 order by 1) x   
 9         start with rn = 1   
10        connect by prior rn = rn - 1   
11               and prior old_name = old_name)   
12 where length(old_name) = length(new_name) 


You would like the result to be:

OLD_NAME NEW_NAME
---------- --------
ADAMS AADMS
ALLEN AELLN
BLAKE ABEKL
CLARK ACKLR
FORD DFOR
JAMES AEJMS
JONES EJNOS
KING GIKN
MARTIN AIMNRT
MILLER EILLMR
SCOTT COSTT
SMITH HIMST
TURNER ENRRTU
WARD ADRW

 

posted on 2008-08-07 14:41 方佳玮 阅读(2755) 评论(6)  编辑  收藏 所属分类: 其他技术

评论

# re: 【整理】sql语句一些实用技巧for oracle 2008-08-07 15:24 天天学习
不是20个吗  回复  更多评论
  

# re: 【整理】sql语句一些实用技巧for oracle 2008-08-07 15:42 方佳玮
稍等,整理发表中  回复  更多评论
  

# re: 【整理】sql语句一些实用技巧for oracle 2008-08-08 01:17 leekiang
赞一个,
我终于知道什么叫"奇技淫巧"了。
要是把书名也贡献出来就好了。  回复  更多评论
  

# re: 【整理】sql语句一些实用技巧for oracle 2008-08-08 10:02 长江三峡
hoho  回复  更多评论
  

# re: 【整理】sql语句一些实用技巧for oracle 2008-08-08 12:26 xxuu503
第三条无法使用索引  回复  更多评论
  

# re: [整理]sql语句一些实用技巧for oracle 2008-08-12 14:06 vinck
真是没得说 这些方法真绝!  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: