您的位置:首页 > 数据库 > Oracle

ORACLE查询

2016-04-09 17:29 399 查看
使用函数提高查询效率

create table STUDENT

(

STUNO NUMBER not null,

STUNAME VARCHAR2(1000),

SCORE NUMBER,

constraint PK_STUDENT primary key (STUNO)

);

-- Add comments to the columns

comment on column STUDENT.STUNO

is '学号';

comment on column STUDENT.STUNAME

is '姓名';

comment on column STUDENT.SCORE

is '成绩';

insert into STUDENT (STUNO, STUNAME, SCORE)

values (1, '张三', 78);

insert into STUDENT (STUNO, STUNAME, SCORE)

values (2, '李四', 92);

insert into STUDENT (STUNO, STUNAME, SCORE)

values (3, '王五', 67);

insert into STUDENT (STUNO, STUNAME, SCORE)

values (4, '赵六', 88);

1.使用集合(低效)

SELECT STUNAME, SCORE, '优'

FROM STUDENT

WHERE SCORE >= 90

UNION ALL

SELECT STUNAME, SCORE, '良'

FROM STUDENT

WHERE SCORE >= 80

AND SCORE < 90

UNION ALL

SELECT STUNAME, SCORE, '中'

FROM STUDENT

WHERE SCORE >= 60

AND SCORE < 80

UNION ALL

SELECT STUNAME, SCORE, '差' FROM STUDENT WHERE SCORE < 60;

SQL> SELECT STUNAME, SCORE, '优'

2 FROM STUDENT

3 WHERE SCORE >= 90

4 UNION ALL

5 SELECT STUNAME, SCORE, '良'

6 FROM STUDENT

7 WHERE SCORE >= 80

8 AND SCORE < 90

9 UNION ALL

10 SELECT STUNAME, SCORE, '中'

11 FROM STUDENT

12 WHERE SCORE >= 60

13 AND SCORE < 80

14 UNION ALL

15 SELECT STUNAME, SCORE, '差' FROM STUDENT WHERE SCORE < 60;

STUNAME SCORE '

-------------------- ---------- --

李四 92 优

赵六 88 良

张三 78 中

王五 67 中

2.使用decode函数(高效) sign() 大于0返回1 小于0返回-1 等于0 返回0

--- sign()如果是-1表示不嵌套,0表示嵌套,decode最后一层else表示等级,以此类推,直到计算到socre-60这一级

SELECT STUNAME,

SCORE,

decode(sign(score - 90),

-1,

decode(sign(score - 80),

-1,

decode(sign(score - 60), -1, '差', '中'),

'良'),

'优')

FROM STUDENT;

SQL> SELECT STUNAME,

2 SCORE,

3 DECODE(SIGN(SCORE - 90),

4 -1,

5 DECODE(SIGN(SCORE - 80),

6 -1,

7 DECODE(SIGN(SCORE - 60), -1, '差', '中'),

8 '良'),

9 '优')

10 FROM STUDENT;

STUNAME SCORE DE

-------------------- ---------- --

张三 78 中

李四 92 优

王五 67 中

赵六 88 良<pre class="sql" name="code">DROP TABLE RESULT;

create table RESULT(rq VARCHAR2(10),SHENGFU VARCHAR2(2));

insert into result values('2005-05-09','胜');

insert into result values('2005-05-09','胜');

insert into result values('2005-05-09','负');

insert into result values('2005-05-09','负');

insert into result values('2005-05-10','胜');

insert into result values('2005-05-10','负');

insert into result values('2005-05-10','负');

COMMIT;

如果要生成下列结果, 该如何写sql语句?

胜 负

2005-05-09 2 2

2005-05-10 1 2

解答:

a,第一种方式

1.根据RQ进行group by 操作,即根据时间进行分组,

2.再求出同一时间胜和负的合计值

SELECT RQ,

SUM(CASE

WHEN SHENGFU = '胜' THEN

1

ELSE

0

END) 胜,

SUM(CASE

WHEN SHENGFU = '负' THEN

1

ELSE

0

END) 负

FROM RESULT

GROUP BY RQ;

SQL> SELECT RQ,

2 SUM(CASE

3 WHEN SHENGFU = '胜' THEN

4 1

5 ELSE

6 0

7 END) 胜,

8 SUM(CASE

9 WHEN SHENGFU = '负' THEN

10 1

11 ELSE

12 0

13 END) 负

14 FROM RESULT

15 GROUP BY RQ;

RQ 胜 负

---------- ---------- ----------

2005-05-10 1 2

2005-05-09 2 2

b.第二种方式

1.分别查询胜的次数及其时间,

2.再把两个结果集进行内连接

SELECT N.RQ, N.胜, M.负

FROM (SELECT RQ, COUNT(*) AS 胜

FROM RESULT

WHERE SHENGFU = '胜'

GROUP BY RQ) N

INNER JOIN (SELECT RQ, COUNT(*) AS 负

FROM RESULT

WHERE SHENGFU = '负'

GROUP BY RQ) M ON N.RQ = M.RQ;

SQL> SELECT N.RQ, N.胜, M.负

2 FROM (SELECT RQ, COUNT(*) AS 胜

3 FROM RESULT

4 WHERE SHENGFU = '胜'

5 GROUP BY RQ) N

6 INNER JOIN (SELECT RQ, COUNT(*) AS 负

7 FROM RESULT

8 WHERE SHENGFU = '负'

9 GROUP BY RQ) M ON N.RQ = M.RQ;

RQ 胜 负

---------- ---------- ----------

2005-05-10 1 2

2005-05-09 2 2

c.第三种方式

1.分别查询胜的次数及其时间

2、通过等值条件进行连接起来

SELECT N.RQ, N.胜, M.负

FROM (SELECT RQ, COUNT(*) AS 胜

FROM RESULT

WHERE SHENGFU = '胜'

GROUP BY RQ) N, (SELECT RQ, COUNT(*) AS 负

FROM RESULT

WHERE SHENGFU = '负'

GROUP BY RQ) M

WHERE N.RQ = M.RQ;

SQL> SELECT N.RQ, N.胜, M.负

2 FROM (SELECT RQ, COUNT(*) AS 胜

3 FROM RESULT

4 WHERE SHENGFU = '胜'

5 GROUP BY RQ) N, (SELECT RQ, COUNT(*) AS 负

6 FROM RESULT

7 WHERE SHENGFU = '负'

8 GROUP BY RQ) M

9 WHERE N.RQ = M.RQ;

RQ 胜 负

---------- ---------- ----------

2005-05-10 1 2

2005-05-09 2 2<pre class="sql" name="code">怎么把这样一个表儿

year month amount

1991 1 1.1

1991 2 1.2

1991 3 1.3

1991 4 1.4

1992 1 2.1

1992 2 2.2

1992 3 2.3

1992 4 2.4

查成这样一个结果

year m1 m2 m3 m4

1991 1.1 1.2 1.3 1.4

1992 2.1 2.2 2.3 2.4

create table AMOUNT

(

YEAR VARCHAR2(4),

MONTH VARCHAR2(2),

AMOUNT NUMBER(15,2)

);

insert into amount (YEAR, MONTH, AMOUNT)

values ('1991', '1', 1.10);

insert into amount (YEAR, MONTH, AMOUNT)

values ('1991', '2', 1.20);

insert into amount (YEAR, MONTH, AMOUNT)

values ('1991', '3', 1.30);

insert into amount (YEAR, MONTH, AMOUNT)

values ('1991', '4', 1.40);

insert into amount (YEAR, MONTH, AMOUNT)

values ('1992', '1', 2.10);

insert into amount (YEAR, MONTH, AMOUNT)

values ('1992', '2', 2.20);

insert into amount (YEAR, MONTH, AMOUNT)

values ('1992', '3', 2.30);

insert into amount (YEAR, MONTH, AMOUNT)

values ('1992', '4', 2.40);

思路:group by year统计年,再条件判断每个月,统计所在月,所在月的合计值显示出来select year,

(select sum(amount)

from amount m

where month = 1

and m.year = amount.year) as m1,

(select sum(amount)

from amount m

where month = 2

and m.year = amount.year) as m2,

(select sum(amount)

from amount m

where month = 3

and m.year = amount.year) as m3,

(select sum(amount)

from amount m

where month = 4

and m.year = amount.year) as m4

from amount

group by year;

SQL> select year,

2 (select sum(amount)

3 from amount m

4 where month = 1

5 and m.year = amount.year) as m1,

6 (select sum(amount)

7 from amount m

8 where month = 2

9 and m.year = amount.year) as m2,

10 (select sum(amount)

11 from amount m

12 where month = 3

13 and m.year = amount.year) as m3,

14 (select sum(amount)

15 from amount m

16 where month = 4

17 and m.year = amount.year) as m4

18 from amount

19 group by year;

YEAR M1 M2 M3 M4

---- ---------- ---------- ---------- ----------

1991 1.1 1.2 1.3 1.4

1992 2.1 2.2 2.3 2.4<pre class="sql" name="code">查询员工服务的年限

SELECT ENAME,

TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) YEAR,

TRUNC(MOD(MONTHS_BETWEEN(SYSDATE, HIREDATE), 12)) MONTH,

TRUNC(MOD(SYSDATE - HIREDATE, 30)) DAY

FROM EMP;

SQL> SELECT ENAME,

2 TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) YEAR,

3 TRUNC(MOD(MONTHS_BETWEEN(SYSDATE, HIREDATE), 12)) MONT

4 TRUNC(MOD(SYSDATE - HIREDATE, 30)) DAY

5 FROM EMP;

ENAME YEAR MONTH DAY

---------- ---------- ---------- ----------

SMITH 34 7 13

ALLEN 34 5 8

WARD 34 5 6

JONES 34 3 27

MARTIN 33 10 28

BLAKE 34 2 28

CLARK 34 1 19

SCOTT 28 3 9

KING 33 8 8

TURNER 33 10 18

ADAMS 28 2 5

ENAME YEAR MONTH DAY

---------- ---------- ---------- ----------

JAMES 33 7 22

FORD 33 7 22

MILLER 33 6 1

已选择14行。<pre class="sql" name="code">统计每年入职的员工个数,效果如下:

TOTAL 1980 1981 1982 1987 1990

-------- ---------- ---------- ---------- ---------- ----------

14 1 10 1 2 0

方式一:

思路:

通过group by 入职日期的年份来获取,适用统计所有年份的入职人数

select to_char(hiredate, 'yyyy') AS 年份, count(*)

from emp

group by to_char(hiredate, 'yyyy')

order by 1

SQL>

1 select to_char(hiredate, 'yyyy') AS 年份, count(*)

2 from emp

3 group by to_char(hiredate, 'yyyy')

4* order by 1

SQL> /

年份 COUNT(*)

---- ----------

1980 1

1981 10

1982 1

1987 2

方式二:

显示总数,并按条件求每年的入职人数(繁锁,但显示直观,适用统计特定年份的人数,查询次数多)

select (select count(*) from emp) total,

(select count(*) from emp where to_char(hiredate, 'yyyy') = '1980') "1980",

(select count(*) from emp where to_char(hiredate, 'yyyy') = '1981') "1981",

(select count(*) from emp where to_char(hiredate, 'yyyy') = '1982') "1982",

(select count(*) from emp where to_char(hiredate, 'yyyy') = '1987') "1987",

(select count(*) from emp where to_char(hiredate, 'yyyy') = '1990') "1990"

from emp

where rownum = 1

1 select

2 (select count(*) from emp) total,

3 (select count(*) from emp where to_char(hiredate, 'yyyy')='1980') "1980",

4 (select count(*) from emp where to_char(hiredate, 'yyyy')='1981') "1981",

5 (select count(*) from emp where to_char(hiredate, 'yyyy')='1982') "1982",

6 (select count(*) from emp where to_char(hiredate, 'yyyy')='1987') "1987",

7 (select count(*) from emp where to_char(hiredate, 'yyyy')='1990') "1990"

8 from

9 emp

10 where

11* rownum=1

SQL> /

TOTAL 1980 1981 1982 1987 1990

---------- ---------- ---------- ---------- ---------- ----------

14 1 10 1 2 0

方法三:

思路:

和方法二显示的效果相同 ,但是比第二种方法优,通过函数判断,减少查询次数

select count(*) total,

sum(Decode(to_char(hiredate, 'yyyy'), '1980', 1, 0)) "1980",

sum(Decode(to_char(hiredate, 'yyyy'), '1981', 1, 0)) "1981",

sum(Decode(to_char(hiredate, 'yyyy'), '1982', 1, 0)) "1982",

sum(Decode(to_char(hiredate, 'yyyy'), '1987', 1, 0)) "1987",

sum(Decode(to_char(hiredate, 'yyyy'), '1990', 1, 0)) "1990"

from emp

1 select

2 count(*) total,

3 sum(Decode(to_char(hiredate, 'yyyy'), '1980', 1, 0)) "1980",

4 sum(Decode(to_char(hiredate, 'yyyy'), '1981', 1, 0)) "1981",

5 sum(Decode(to_char(hiredate, 'yyyy'), '1982', 1, 0)) "1982",

6 sum(Decode(to_char(hiredate, 'yyyy'), '1987', 1, 0)) "1987",

7 sum(Decode(to_char(hiredate, 'yyyy'), '1990', 1, 0)) "1990"

8 from

9* emp

SQL> /

TOTAL 1980 1981 1982 1987 1990

---------- ---------- ---------- ---------- ---------- ----------

14 1 10 1 2 0

获取当前时间,显示为 xxxx年xx月xx日 xx时xx分xx秒 的格式

SQL(使用双引号向日期格式中添加字符):

select to_char(sysdate, 'yyyy"年"mm"月"dd"日" hh"时"mi"分"ss"秒"') from dual;

结果:

TO_CHAR(SYSDATE,'YYYY"年"MM

---------------------------

2012年03月08日 01时04分01秒

假如数据量很大约1000万条,写一个你认为最高效的SQL,用一个SQL计算以下四种人

sal>9999 and age>35

sal>9999 and age<35

sal<9999 and age>35

sal<9999 and age>35

case when方式

select sum(case

when sal > 9999 and

TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) > 35 then

1

else

0

end) A,

sum(case

when sal > 9999 and

TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) < 35 then

1

else

0

end) B,

sum(case

when sal < 9999 and

TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) > 35 then

1

else

0

end) C,

sum(case

when sal < 9999 and

TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) < 35 then

1

else

0

end) D

from emp;

SQL> select sum(case

2 when sal > 9999 and

3 TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) > 35 then

4 1

5 else

6 0

7 end) A,

8 sum(case

9 when sal > 9999 and

10 TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) < 35 then

11 1

12 else

13 0

14 end) B,

15 sum(case

16 when sal < 9999 and

17 TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) > 35 then

18 1

19 else

20 0

21 end) C,

22 sum(case

23 when sal < 9999 and

24 TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) < 35 then

25 1

26 else

27 0

28 end) D

29 from emp;

A B C D

---------- ---------- ---------- ----------

0 0 0 17

Oracle层级查询

--层次化查询,注意prior是Oracle内置的操作符,仅用来处理层次化查询

select level,

lpad(' ', 2 * (level - 1)) || last_name "EmpName",

employee_id,

manager_id,

first_name,

last_name,

hire_date

from employees

--表示根节点为manager_id

start with manager_id is null

--prior表示父行的employee_id,等于当前行的manager_id

connect by manager_id = prior employee_id

order by level;



</listener>

说明:本人于ITEYE创建于2013年,现转移到CSDN

</listener>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: