数据库编程2 Oracle 过滤 函数 分组 外连接 自连接

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库编程2 Oracle 过滤 函数 分组 外连接 自连接相关的知识,希望对你有一定的参考价值。

本文谢绝转载原文来自http://990487026.blog.51cto.com

续:数据库编程1 Oracle 过滤 函数 分组 外连接 自连接



where like模糊查询,查询员工姓名是4个字母

SQL> select * from emp where ename like ‘____‘;

     EMPNO ENAME                JOB                       MGR HIREDATE          SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- ---------- ---------- ---------- ----------
      7521 WARD                 SALESMAN                 7698 1981-02-22       1250        500         30
      7839 KING                 PRESIDENT                     1981-11-17       5000                    10
      7902 FORD                 ANALYST                  7566 1981-12-03       3000                    20

SQL>


where like模糊查询,转义字符

SQL> set linesize 59
SQL> desc emp;
 名称                         是否为空? 类型
 ---------------------------- -------- --------------------
 EMPNO                        NOT NULL NUMBER(4)
 ENAME                                 VARCHAR2(10)
 JOB                                   VARCHAR2(9)
 MGR                                   NUMBER(4)
 HIREDATE                              DATE
 SAL                                   NUMBER(7,2)
 COMM                                  NUMBER(7,2)
 DEPTNO                                NUMBER(2)

SQL>

插入一条新的内容:
SQL> insert into emp(empno,ename,sal,deptno) values(1,‘tom_abc‘,8000,10);

已创建 1 行。


查看插入的结果:
SQL> set linesize 199
SQL> select * from emp;

     EMPNO ENAME                JOB                       MGR HIREDATE          SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- ---------- ---------- ---------- ----------
      7369 SMITH                CLERK                    7902 1980-12-17        800                    20
      7499 ALLEN                SALESMAN                 7698 1981-02-20       1600        300         30
      7521 WARD                 SALESMAN                 7698 1981-02-22       1250        500         30
      7566 JONES                MANAGER                  7839 1981-04-02       2975                    20
      7654 MARTIN               SALESMAN                 7698 1981-09-28       1250       1400         30
      7698 BLAKE                MANAGER                  7839 1981-05-01       2850                    30
      7782 CLARK                MANAGER                  7839 1981-06-09       2450                    10
      7788 SCOTT                ANALYST                  7566 1987-04-19       3000                    20
      7839 KING                 PRESIDENT                     1981-11-17       5000                    10
      7844 TURNER               SALESMAN                 7698 1981-09-08       1500          0         30
      7876 ADAMS                CLERK                    7788 1987-05-23       1100                    20
      7900 JAMES                CLERK                    7698 1981-12-03        950                    30
      7902 FORD                 ANALYST                  7566 1981-12-03       3000                    20
      7934 MILLER               CLERK                    7782 1982-01-23       1300                    10
         1 tom_abc                                                             8000                    10

已选择15行。


SQL> select * from emp where ename like ‘%\_%‘ escape ‘\‘;

     EMPNO ENAME                JOB                       MGR HIREDATE          SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- ---------- ---------- ---------- ----------
         1 tom_abc                                                             8000                    10

SQL>



where order by 工资排序,默认升序

SQL> select * from emp order by sal;

     EMPNO ENAME                JOB                       MGR HIREDATE          SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- ---------- ---------- ---------- ----------
      7369 SMITH                CLERK                    7902 1980-12-17        800                    20
      7900 JAMES                CLERK                    7698 1981-12-03        950                    30
      7876 ADAMS                CLERK                    7788 1987-05-23       1100                    20
      7521 WARD                 SALESMAN                 7698 1981-02-22       1250        500         30
      7654 MARTIN               SALESMAN                 7698 1981-09-28       1250       1400         30
      7934 MILLER               CLERK                    7782 1982-01-23       1300                    10
      7844 TURNER               SALESMAN                 7698 1981-09-08       1500          0         30
      7499 ALLEN                SALESMAN                 7698 1981-02-20       1600        300         30
      7782 CLARK                MANAGER                  7839 1981-06-09       2450                    10
      7698 BLAKE                MANAGER                  7839 1981-05-01       2850                    30
      7566 JONES                MANAGER                  7839 1981-04-02       2975                    20
      7902 FORD                 ANALYST                  7566 1981-12-03       3000                    20
      7788 SCOTT                ANALYST                  7566 1987-04-19       3000                    20
      7839 KING                 PRESIDENT                     1981-11-17       5000                    10
         1 tom_abc                                                             8000                    10

已选择15行。




where order by 别名

SQL> select empno,ename,sal,sal*12 年薪 from emp order by 年薪;

     EMPNO ENAME                       SAL       年薪
---------- -------------------- ---------- ----------
      7369 SMITH                       800       9600
      7900 JAMES                       950      11400
      7876 ADAMS                      1100      13200
      7521 WARD                       1250      15000
      7654 MARTIN                     1250      15000
      7934 MILLER                     1300      15600
      7844 TURNER                     1500      18000
      7499 ALLEN                      1600      19200
      7782 CLARK                      2450      29400
      7698 BLAKE                      2850      34200
      7566 JONES                      2975      35700
      7902 FORD                       3000      36000
      7788 SCOTT                      3000      36000
      7839 KING                       5000      60000
         1 tom_abc                    8000      96000

已选择15行。






order by 遇到null

1,任何表达式与null运算都为空

2,null!=null



nulls last 把null放在最后

SQL> select empno,ename,sal,comm 奖金 from emp order by 4 desc;

     EMPNO ENAME                       SAL       奖金
---------- -------------------- ---------- ----------
      7369 SMITH                       800
      7788 SCOTT                      3000
      7934 MILLER                     1300
      7902 FORD                       3000
      7900 JAMES                       950
      7566 JONES                      2975
      7698 BLAKE                      2850
      7782 CLARK                      2450
         1 tom_abc                    8000
      7839 KING                       5000
      7876 ADAMS                      1100
      7654 MARTIN                     1250       1400
      7521 WARD                       1250        500
      7499 ALLEN                      1600        300
      7844 TURNER                     1500          0

已选择15行。

SQL> select empno,ename,sal,comm 奖金 from emp order by 4 desc nulls last;

     EMPNO ENAME                       SAL       奖金
---------- -------------------- ---------- ----------
      7654 MARTIN                     1250       1400
      7521 WARD                       1250        500
      7499 ALLEN                      1600        300
      7844 TURNER                     1500          0
         1 tom_abc                    8000
      7839 KING                       5000
      7876 ADAMS                      1100
      7900 JAMES                       950
      7902 FORD                       3000
      7934 MILLER                     1300
      7782 CLARK                      2450
      7698 BLAKE                      2850
      7566 JONES                      2975
      7369 SMITH                       800
      7788 SCOTT                      3000

已选择15行。

SQL>


order修饰多个列,desc的作用范围只是最近的哪一个!

SQL> select * from emp order by deptno desc, sal desc;

     EMPNO ENAME                JOB                       MGR HIREDATE          SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- ---------- ---------- ---------- ----------
      7698 BLAKE                MANAGER                  7839 1981-05-01       2850                    30
      7499 ALLEN                SALESMAN                 7698 1981-02-20       1600        300         30
      7844 TURNER               SALESMAN                 7698 1981-09-08       1500          0         30
      7521 WARD                 SALESMAN                 7698 1981-02-22       1250        500         30
      7654 MARTIN               SALESMAN                 7698 1981-09-28       1250       1400         30
      7900 JAMES                CLERK                    7698 1981-12-03        950                    30
      7788 SCOTT                ANALYST                  7566 1987-04-19       3000                    20
      7902 FORD                 ANALYST                  7566 1981-12-03       3000                    20
      7566 JONES                MANAGER                  7839 1981-04-02       2975                    20
      7876 ADAMS                CLERK                    7788 1987-05-23       1100                    20
      7369 SMITH                CLERK                    7902 1980-12-17        800                    20
         1 tom_abc                                                             8000                    10
      7839 KING                 PRESIDENT                     1981-11-17       5000                    10
      7782 CLARK                MANAGER                  7839 1981-06-09       2450                    10
      7934 MILLER               CLERK                    7782 1982-01-23       1300                    10

已选择15行。


count函数

SQL> select * from emp ;

     EMPNO ENAME                JOB                       MGR HIREDATE          SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- ---------- ---------- ---------- ----------
      7369 SMITH                CLERK                    7902 1980-12-17        800                    20
      7499 ALLEN                SALESMAN                 7698 1981-02-20       1600        300         30
      7521 WARD                 SALESMAN                 7698 1981-02-22       1250        500         30
      7566 JONES                MANAGER                  7839 1981-04-02       2975                    20
      7654 MARTIN               SALESMAN                 7698 1981-09-28       1250       1400         30
      7698 BLAKE                MANAGER                  7839 1981-05-01       2850                    30
      7782 CLARK                MANAGER                  7839 1981-06-09       2450                    10
      7788 SCOTT                ANALYST                  7566 1987-04-19       3000                    20
      7839 KING                 PRESIDENT                     1981-11-17       5000                    10
      7844 TURNER               SALESMAN                 7698 1981-09-08       1500          0         30
      7876 ADAMS                CLERK                    7788 1987-05-23       1100                    20
      7900 JAMES                CLERK                    7698 1981-12-03        950                    30
      7902 FORD                 ANALYST                  7566 1981-12-03       3000                    20
      7934 MILLER               CLERK                    7782 1982-01-23       1300                    10
         1 tom_abc                                                             8000                    10

已选择15行。

SQL> select count(*) from emp ;

  COUNT(*)
----------
        15


字符函数

         大小写转换函数

LOWER

UPPER

INITCAP

SQL> select lower(‘HEllo‘)转小写,upper(‘hello‘)转大写,initcap(‘hello WORLD‘)首字母大写 from dual;
转小写     转大写     首字母大写
---------- ---------- ----------------------
hello      HELLO      Hello World
		


==============================================
字符串连接:
SQL> select concat(‘Hello‘,‘ haha‘) from dual;

CONCAT(‘HELLO‘,‘HAHA
--------------------
Hello haha


函数嵌套:

SQL> select concat(‘qqqqqqqqqqq ‘, concat(‘Hello‘,‘ haha‘)) from dual;

CONCAT(‘QQQQQQQQQQQ‘,CONCAT(‘HELLO‘,‘HAHA‘))
--------------------------------------------
qqqqqqqqqqq Hello haha




substr(a,b) 从a中第b位开始取字符串:

substr(a,b,c) 从a中第b位开始取c个字符:

SQL> select substr(‘1234567890‘,2) , substr(‘1234567890‘,4,4) from dual;

SUBSTR(‘1234567890 SUBSTR(‘
------------------ --------
234567890          4567


length 字符数

lengthb 字节数

SQL> select length(‘中国abc‘) 字符数,lengthb(‘中国abc‘) from dual;

    字符数 LENGTHB(‘中国ABC‘)
---------- ------------------
         5                  9
因为从上面可以看出我们的系统是字符是UTF



instr求子串的位置;

SQL> select instr(‘123456‘,‘345‘) from dual;

INSTR(‘123456‘,‘345‘)
---------------------
                    3



lpad,rpad左填充右填充:

SQL> select lpad(‘abcd‘,10,‘*‘),rpad(‘1234‘,10,‘@‘) from dual;

LPAD(‘ABCD‘,10,‘*‘)  RPAD(‘1234‘,10,‘@‘)
-------------------- --------------------
******abcd           [email protected]@@@@@


trim去除前后指定字符:

SQL> select trim(‘A‘ from ‘AB1231342141412A‘)  from dual;

TRIM(‘A‘FROM‘AB1231342141412
----------------------------
B1231342141412



replace 字符串替换

SQL> select  replace (‘111222333444‘,‘222‘,‘hahahaa‘) from dual;

REPLACE(‘111222333444‘,‘222‘,‘HA
--------------------------------
111hahahaa333444



round 四舍五入

参数2大于0  表保留小数点位数

参数2等于0  表保留小数点到个位

参数2等于-1  表保留小数点到十位

参数2等于-2  表保留小数点到百位

SQL> select round(45.4666,2) from dual;

ROUND(45.4666,2)
----------------
           45.47

SQL> select round(45.4666,0) from dual;

ROUND(45.4666,0)
----------------
              45

SQL> select round(45.4666,-1) from dual;

ROUND(45.4666,-1)
-----------------
               50

SQL> select round(145.7266,-2) from dual;

ROUND(145.7266,-2)
------------------
               100


tuec截断函数

SQL> select trunc(145.7266,2) from dual;

TRUNC(145.7266,2)
-----------------
           145.72


mod求余函数

SQL> select mod(145,100) from dual;

MOD(145,100)
------------
          45



2,时间处理函数

to_char格式化输出:

SQL> select to_char(sysdate,‘yyyy-mm-dd hh24:mi:ss‘) from dual;

TO_CHAR(SYSDATE,‘YYYY-MM-DDHH24:MI:SS‘
--------------------------------------
2016-08-25 11:32:17





SQL> select to_char(sysdate-1,‘yyyy-mm-dd hh24:mi:ss‘) 昨天 from dual;

昨天
--------------------------------------
2016-08-24 11:34:44






SQL> select to_char(sysdate+1,‘yyyy-mm-dd hh24:mi:ss‘) 明天 from dual;

明天
--------------------------------------
2016-08-26 11:35:18





两个日期相减,返回日期之间相差的天数

SQL> select ename , (sysdate-hiredate) from emp;

ENAME                (SYSDATE-HIREDATE)
-------------------- ------------------
SMITH                         13035.495
ALLEN                         12970.495
WARD                          12968.495
JONES                         12929.495
MARTIN                        12750.495
BLAKE                         12900.495
CLARK                         12861.495
SCOTT                         10721.495
KING                          12700.495
TURNER                        12770.495
ADAMS                         10687.495
JAMES                         12684.495
FORD                          12684.495
MILLER                        12633.495
tom_abc

已选择15行。




精确显示员工入职月数,时间运算months_between

SQL> select ename , (sysdate-hiredate)/30 估计月 ,months_between(sysdate,hiredate) 函数计算月 from emp;

ENAME                    估计月 函数计算月
-------------------- ---------- ----------
SMITH                434.522107 428.279459
ALLEN                432.355441 426.182684
WARD                 432.288774 426.118168
JONES                430.988774  424.76333
MARTIN               425.022107  418.92462
BLAKE                430.022107 423.795588
CLARK                428.722107 422.537523
SCOTT                357.388774 352.214943
KING                 423.355441 417.279459
TURNER               425.688774 419.569781
ADAMS                356.255441  351.08591
JAMES                422.822107 416.731072
FORD                 422.822107 416.731072
MILLER               421.122107  415.08591
tom_abc

已选择15行。



add_months()向指定的日期中加若干的月数


next_day();下一个指定的日期

SQL> select next_day(sysdate,‘星期六‘) from dual;

NEXT_DAY(SYSDA
--------------
27-8月 -16


3,数据类型转换:


3,1隐式转换,字符串转日期

SQL> select * from emp where hiredate >‘01-1月 -81‘;

     EMPNO ENAME                JOB                       MGR HIREDATE              SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- -------------- ---------- ---------- ----------
      7499 ALLEN                SALESMAN                 7698 20-2月 -81           1600        300      30
      7521 WARD                 SALESMAN                 7698 22-2月 -81           1250        500      30
      7566 JONES                MANAGER                  7839 02-4月 -81           2975                 20
      7654 MARTIN               SALESMAN                 7698 28-9月 -81           1250       1400      30
      7698 BLAKE                MANAGER                  7839 01-5月 -81           2850                 30
      7782 CLARK                MANAGER                  7839 09-6月 -81           2450                 10
      7788 SCOTT                ANALYST                  7566 19-4月 -87           3000                 20
      7839 KING                 PRESIDENT                     17-11月-81           5000                 10
      7844 TURNER               SALESMAN                 7698 08-9月 -81           1500          0      30
      7876 ADAMS                CLERK                    7788 23-5月 -87           1100                 20
      7900 JAMES                CLERK                    7698 03-12月-81            950                 30
      7902 FORD                 ANALYST                  7566 03-12月-81           3000                 20
      7934 MILLER               CLERK                    7782 23-1月 -82           1300                 10

已选择13行。

3,1显示转换,字符串转日期

SQL> select * from emp where hiredate > to_date(‘1981-01-01 12:30:55‘,‘yyyy-mm-dd hh24:mi:ss‘);

     EMPNO ENAME                JOB                       MGR HIREDATE              SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- -------------- ---------- ---------- ----------
      7499 ALLEN                SALESMAN                 7698 20-2月 -81           1600        300      30
      7521 WARD                 SALESMAN                 7698 22-2月 -81           1250        500      30
      7566 JONES                MANAGER                  7839 02-4月 -81           2975                 20
      7654 MARTIN               SALESMAN                 7698 28-9月 -81           1250       1400      30
      7698 BLAKE                MANAGER                  7839 01-5月 -81           2850                 30
      7782 CLARK                MANAGER                  7839 09-6月 -81           2450                 10
      7788 SCOTT                ANALYST                  7566 19-4月 -87           3000                 20
      7839 KING                 PRESIDENT                     17-11月-81           5000                 10
      7844 TURNER               SALESMAN                 7698 08-9月 -81           1500          0      30
      7876 ADAMS                CLERK                    7788 23-5月 -87           1100                 20
      7900 JAMES                CLERK                    7698 03-12月-81            950                 30
      7902 FORD                 ANALYST                  7566 03-12月-81           3000                 20
      7934 MILLER               CLERK                    7782 23-1月 -82           1300                 10

已选择13行。


字符串与字符串比较

SQL> select * from emp where to_char(hiredate,‘yyyy-mm-dd hh24:mi:ss‘)  > ‘1981-01-01 12:30:55‘;

     EMPNO ENAME                JOB                       MGR HIREDATE              SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- -------------- ---------- ---------- ----------
      7499 ALLEN                SALESMAN                 7698 20-2月 -81           1600        300      30
      7521 WARD                 SALESMAN                 7698 22-2月 -81           1250        500      30
      7566 JONES                MANAGER                  7839 02-4月 -81           2975                 20
      7654 MARTIN               SALESMAN                 7698 28-9月 -81           1250       1400      30
      7698 BLAKE                MANAGER                  7839 01-5月 -81           2850                 30
      7782 CLARK                MANAGER                  7839 09-6月 -81           2450                 10
      7788 SCOTT                ANALYST                  7566 19-4月 -87           3000                 20
      7839 KING                 PRESIDENT                     17-11月-81           5000                 10
      7844 TURNER               SALESMAN                 7698 08-9月 -81           1500          0      30
      7876 ADAMS                CLERK                    7788 23-5月 -87           1100                 20
      7900 JAMES                CLERK                    7698 03-12月-81            950                 30
      7902 FORD                 ANALYST                  7566 03-12月-81           3000                 20
      7934 MILLER               CLERK                    7782 23-1月 -82           1300                 10

已选择13行。

to_char()对数字转字符


9 数字

0 零

$ 美元

L 本地货币符号

.小数点

,千位符

SQL> select empno,ename,to_char(sal,‘L9,999.99‘) from emp;

     EMPNO ENAME                TO_CHAR(SAL,‘L9,999.99‘)
---------- -------------------- ----------------------------
      7369 SMITH                          ¥800.00
      7499 ALLEN                        ¥1,600.00
      7521 WARD                         ¥1,250.00
      7566 JONES                        ¥2,975.00
      7654 MARTIN                       ¥1,250.00
      7698 BLAKE                        ¥2,850.00
      7782 CLARK                        ¥2,450.00
      7788 SCOTT                        ¥3,000.00
      7839 KING                         ¥5,000.00
      7844 TURNER                       ¥1,500.00
      7876 ADAMS                        ¥1,100.00
      7900 JAMES                          ¥950.00
      7902 FORD                         ¥3,000.00
      7934 MILLER                       ¥1,300.00
         1 tom_abc                      ¥8,000.00

已选择15行。



to_number()字符转数字

SQL> select to_number(‘¥8,000.00‘,‘L9,999.99‘) from dual;

TO_NUMBER(‘¥8,000.00‘,‘L9,999.99‘)
-----------------------------------
                               8000


4,通用函数


nvl2(a,b,c)当a为null时返回c,否则返回b

SQL>  select sal ,sal*12+nvl2(comm,comm,0) 年收入 from emp;

       SAL     年收入
---------- ----------
       800       9600
      1600      19500
      1250      15500
      2975      35700
      1250      16400
      2850      34200
      2450      29400
      3000      36000
      5000      60000
      1500      18000
      1100      13200
       950      11400
      3000      36000
      1300      15600
      8000      96000

已选择15行。




nullif(a,b)当a,b相等时返回NULL,否则返回a

SQL> select nullif(‘abc‘,‘abcd‘) from dual;

NULLIF
------
abc

SQL> select nullif(‘abc‘,‘abc‘) from dual;

NULLIF
------


SQL>




案例:总裁涨1000,经理涨800,其他涨500

方法1,SQL规范方法:

select ename,job,sal 涨前工资,
(
	case job when ‘PRESIDENT‘ then sal +1000
		when ‘MANAGER‘ then sal +800
		else sal+500
	end
)
涨工资后 from emp;
ENAME                JOB                  涨前工资   涨工资后
-------------------- ------------------ ---------- ----------
SMITH                CLERK                     800       1300
ALLEN                SALESMAN                 1600       2100
WARD                 SALESMAN                 1250       1750
JONES                MANAGER                  2975       3775
MARTIN               SALESMAN                 1250       1750
BLAKE                MANAGER                  2850       3650
CLARK                MANAGER                  2450       3250
SCOTT                ANALYST                  3000       3500
KING                 PRESIDENT                5000       6000
TURNER               SALESMAN                 1500       2000
ADAMS                CLERK                    1100       1600
JAMES                CLERK                     950       1450
FORD                 ANALYST                  3000       3500
MILLER               CLERK                    1300       1800
tom_abc                                       8000       8500

已选择15行。


方法2:Oracle专有方法

select ename,job,sal 涨前工资,
(
	decode(job,‘PERMANENT‘,sal+1000,‘MANAGER‘,sal+800,sal+500)
)
涨工资后 from emp;
-----------------------------------------------------
SQL> select ename,job,sal 涨前工资,
  2  (
  3     decode(job,‘PERMANENT‘,sal+1000,‘MANAGER‘,sal+800,sal+500)
  4  )
  5  涨工资后 from emp;

ENAME                JOB                  涨前工资   涨工资后
-------------------- ------------------ ---------- ----------
SMITH                CLERK                     800       1300
ALLEN                SALESMAN                 1600       2100
WARD                 SALESMAN                 1250       1750
JONES                MANAGER                  2975       3775
MARTIN               SALESMAN                 1250       1750
BLAKE                MANAGER                  2850       3650
CLARK                MANAGER                  2450       3250
SCOTT                ANALYST                  3000       3500
KING                 PRESIDENT                5000       5500
TURNER               SALESMAN                 1500       2000
ADAMS                CLERK                    1100       1600
JAMES                CLERK                     950       1450
FORD                 ANALYST                  3000       3500
MILLER               CLERK                    1300       1800
tom_abc                                       8000       8500

已选择15行。


组函数:

SQL> select avg(sal),sum(sal),max(sal),min(sal),count(sal) from emp;

  AVG(SAL)   SUM(SAL)   MAX(SAL)   MIN(SAL) COUNT(SAL)
---------- ---------- ---------- ---------- ----------
2468.33333      37025       8000        800         15

SQL>


组函数与null在一起

SQL> select avg(comm),sum(comm),max(comm),min(comm),count(comm) from emp;

 AVG(COMM)  SUM(COMM)  MAX(COMM)  MIN(COMM) COUNT(COMM)
---------- ---------- ---------- ---------- -----------
       550       2200       1400          0           4

SQL>



组函数会自动过滤空值:

SQL> select avg(comm)  ,sum(comm)/count(comm)  ,sum(comm)/count(*)   from emp;

 AVG(COMM) SUM(COMM)/COUNT(COMM) SUM(COMM)/COUNT(*)
---------- --------------------- ------------------
       550                   550         146.666667


SQL> select count(comm)  ,count(*)   from emp;

COUNT(COMM)   COUNT(*)
----------- ----------
        4         15

修正:
SQL> select count(nvl(comm,0))  ,count(*)   from emp;

COUNT(NVL(COMM,0))   COUNT(*)
------------------ ----------
                15         15	



分组数据:

求出各个部门的平均工资:

SQL> select deptno,avg(sal) from emp group by deptno;

    DEPTNO   AVG(SAL)
---------- ----------
        30 1566.66667
        20       2175
        10     4187.5

SQL>

group by 注意:


select a,c,b from tab group by a,b,c,d; --ok

select a,c,f from tab group by a,b,c,d; --err

1,select检索的列必须位于group by后面的集合中

2,组函数设计的本意:必须要在分组数据之上进行结果集合的数据检索.






标准错误:

SQL> select deptno,avg(sal),ename from emp group by deptno;
select deptno,avg(sal),ename from emp group by deptno
                       *
第 1 行出现错误:
ORA-00979: 不是 GROUP BY 表达式




分组最难的地方:

求出各个部门中的每种职位 平均工资

SQL> select deptno,job,avg(sal),count(deptno) from emp group by deptno,job order by 1;

    DEPTNO JOB                  AVG(SAL) COUNT(DEPTNO)
---------- ------------------ ---------- -------------
        10 CLERK                    1300             1
        10 MANAGER                  2450             1
        10 PRESIDENT                5000             1
        10                          8000             1
        20 ANALYST                  3000             2
        20 CLERK                     950             2
        20 MANAGER                  2975             1
        30 CLERK                     950             1
        30 MANAGER                  2850             1
        30 SALESMAN                 1400             4

已选择10行。



having 分组过滤:

查询各个部门的平均工资大于2000的部门:

面试:[查询平均工资大于2000的部门]



在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与合计函数一起使用。

SQL> select deptno ,avg(sal) from emp group by deptno having avg(sal) >2000;

    DEPTNO   AVG(SAL)
---------- ----------
        20       2175
        10     4187.5


求10号部门的平均工资的两种方法:where having

1,先分组再过滤

SQL> select deptno,avg(sal) from emp group by deptno having deptno=10;

    DEPTNO   AVG(SAL)
---------- ----------
        10     4187.5


2,先过滤再分组

SQL> select deptno,avg(sal) from emp where deptno=10 group by deptno;

    DEPTNO   AVG(SAL)
---------- ----------
        10     4187.5


SQL优化问题:


select * from emp;

select deptno,ename,......from emp --显式的把所有的列都写出来,速度快,不需要‘翻译‘

select *from emp 

where (deptno=10) and (deptno=20) and (deptno=30) 

Oracle解析方向,从右到左,和C语言的printf函数差不多




多表查询:

SQL> select count(e.empno) from emp e,dept d;

COUNT(E.EMPNO)
--------------
            60

SQL> select count(e.empno) from emp e,dept d where e.deptno=d.deptno;

COUNT(E.EMPNO)
--------------
            15


[等值连接],显示员工信息,员工号,姓名,月薪

SQL> select ename,empno,sal,dept.dname  from emp,dept where emp.deptno = dept.deptno;

ENAME                     EMPNO        SAL DNAME
-------------------- ---------- ---------- ----------------------------
CLARK                      7782       2450 ACCOUNTING
tom_abc                       1       8000 ACCOUNTING
KING                       7839       5000 ACCOUNTING
MILLER                     7934       1300 ACCOUNTING
JONES                      7566       2975 RESEARCH
SMITH                      7369        800 RESEARCH
SCOTT                      7788       3000 RESEARCH
FORD                       7902       3000 RESEARCH
ADAMS                      7876       1100 RESEARCH
TURNER                     7844       1500 SALES
ALLEN                      7499       1600 SALES
JAMES                      7900        950 SALES
WARD                       7521       1250 SALES
MARTIN                     7654       1250 SALES
BLAKE                      7698       2850 SALES

已选择15行。


[不等值连接]显示员工信息,员工号,姓名,月薪,薪水级别

SQL> select e.empno,e.ename,e.sal,s.grade from emp e,salgrade s where e.sal>=s.losal and e.sal<=hisal;

     EMPNO ENAME                       SAL      GRADE
---------- -------------------- ---------- ----------
      7369 SMITH                       800          1
      7900 JAMES                       950          1
      7876 ADAMS                      1100          1
      7521 WARD                       1250          2
      7654 MARTIN                     1250          2
      7934 MILLER                     1300          2
      7844 TURNER                     1500          3
      7499 ALLEN                      1600          3
      7782 CLARK                      2450          4
      7698 BLAKE                      2850          4
      7566 JONES                      2975          4
      7902 FORD                       3000          4
      7788 SCOTT                      3000          4
      7839 KING                       5000          5
         1 tom_abc                    8000          5

已选择15行。


多表查询4,求每个部门的人数:(需要分组)

)
SQL> select *from dept;

    DEPTNO DNAME                        LOC
---------- ---------------------------- ----------
        10 ACCOUNTING                   NEW YORK
        20 RESEARCH                     DALLAS
        30 SALES                        CHICAGO
        40 OPERATIONS                   BOSTON	

	
SQL> select d.deptno,d.dname,count(e.empno) from dept d,emp e where d.deptno=e.deptno group by d.deptno,d.dname;

    DEPTNO DNAME                        COUNT(E.EMPNO)
---------- ---------------------------- --------------
        10 ACCOUNTING                                4
        20 RESEARCH                                  5
        30 SALES                                     6




[少了一个部门,这个方法有漏洞,因为40号部门没有员工] 

[外连接]技术引出:



右外连接,+在等号的左边

SQL> select d.deptno,d.dname,count(e.empno) from dept d,emp e where d.deptno(+)=e.deptno group by d.deptno,d.dname;

    DEPTNO DNAME                        COUNT(E.EMPNO)
---------- ---------------------------- --------------
        10 ACCOUNTING                                4
        20 RESEARCH                                  5
        30 SALES                                     6
===============================================
左外连接,+在等号的右边
SQL> select d.deptno,d.dname,count(e.empno) from dept d,emp e where d.deptno=e.deptno(+) group by d.deptno,d.dname;

    DEPTNO DNAME                        COUNT(E.EMPNO)
---------- ---------------------------- --------------
        10 ACCOUNTING                                4
        40 OPERATIONS                                0
        20 RESEARCH                                  5
        30 SALES                                     6



[难点]:[自连接]

显示老板的信息:

SQL> select *from emp;

     EMPNO ENAME                JOB                       MGR HIREDATE              SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- -------------- ---------- ---------- ----------
      7369 SMITH                CLERK                    7902 17-12月-80            800                 20
      7499 ALLEN                SALESMAN                 7698 20-2月 -81           1600        300      30
      7521 WARD                 SALESMAN                 7698 22-2月 -81           1250        500      30
      7566 JONES                MANAGER                  7839 02-4月 -81           2975                 20
      7654 MARTIN               SALESMAN                 7698 28-9月 -81           1250       1400      30
      7698 BLAKE                MANAGER                  7839 01-5月 -81           2850                 30
      7782 CLARK                MANAGER                  7839 09-6月 -81           2450                 10
      7788 SCOTT                ANALYST                  7566 19-4月 -87           3000                 20
      7839 KING                 PRESIDENT                     17-11月-81           5000                 10
      7844 TURNER               SALESMAN                 7698 08-9月 -81           1500          0      30
      7876 ADAMS                CLERK                    7788 23-5月 -87           1100                 20
      7900 JAMES                CLERK                    7698 03-12月-81            950                 30
      7902 FORD                 ANALYST                  7566 03-12月-81           3000                 20
      7934 MILLER               CLERK                    7782 23-1月 -82           1300                 10
         1 tom_abc                                                                 8000                    10
[这是对的]
SQL> select e.ename 员工,b.ename 老板 from emp e,emp b where e.mgr=b.empno;

员工                 老板
-------------------- --------------------
FORD                 JONES
SCOTT                JONES
TURNER               BLAKE
ALLEN                BLAKE
WARD                 BLAKE
JAMES                BLAKE
MARTIN               BLAKE
MILLER               CLARK
ADAMS                SCOTT
BLAKE                KING
JONES                KING
CLARK                KING
SMITH                FORD

已选择13行。

[这是错误的]
SQL> select a.ename 员工,b.ename 老板 from emp a,emp b where a.empno=b.mgr;

员工                 老板
-------------------- --------------------
JONES                FORD
JONES                SCOTT
BLAKE                TURNER
BLAKE                ALLEN
BLAKE                WARD
BLAKE                JAMES
BLAKE                MARTIN
CLARK                MILLER
SCOTT                ADAMS
KING                 BLAKE
KING                 JONES
KING                 CLARK
FORD                 SMITH

已选择13行。



[优化显示]

SQL> select e.ename ||‘ 的老板是 ‘||b.ename from emp e,emp b where e.mgr=b.empno(+);

E.ENAME||‘的老板是‘||B.ENAME
--------------------------------------------------------------------
FORD 的老板是 JONES
SCOTT 的老板是 JONES
JAMES 的老板是 BLAKE
TURNER 的老板是 BLAKE
MARTIN 的老板是 BLAKE
WARD 的老板是 BLAKE
ALLEN 的老板是 BLAKE
MILLER 的老板是 CLARK
ADAMS 的老板是 SCOTT
CLARK 的老板是 KING
BLAKE 的老板是 KING
JONES 的老板是 KING
SMITH 的老板是 FORD
tom_abc 的老板是
KING 的老板是


[再优化]

SQL> select e.ename ||‘ 的老板是 ‘|| nvl(b.ename,‘他自己‘) from emp e,emp b where e.mgr=b.empno(+);

E.ENAME||‘的老板是‘||NVL(B.ENAME,‘他自己‘)
--------------------------------------------------------------------
FORD 的老板是 JONES
SCOTT 的老板是 JONES
JAMES 的老板是 BLAKE
TURNER 的老板是 BLAKE
MARTIN 的老板是 BLAKE
WARD 的老板是 BLAKE
ALLEN 的老板是 BLAKE
MILLER 的老板是 CLARK
ADAMS 的老板是 SCOTT
CLARK 的老板是 KING
BLAKE 的老板是 KING
JONES 的老板是 KING
SMITH 的老板是 FORD
tom_abc 的老板是 他自己
KING 的老板是 他自己


[难点]:

1,查询每个部门的人数

分析:需要使用分组

分析:需要外连接(把部门为空的部门也显示出来)

SQL> select d.deptno,d.dname,count(e.ename)  from emp e, dept d where d.deptno=e.deptno(+)  group by d.deptno, d.dname order by d.deptno;

    DEPTNO DNAME                        COUNT(E.ENAME)
---------- ---------------------------- --------------
        10 ACCOUNTING                                4
        20 RESEARCH                                  5
        30 SALES                                     6
        40 OPERATIONS                                0






本文出自 “魂斗罗” 博客,谢绝转载!

以上是关于数据库编程2 Oracle 过滤 函数 分组 外连接 自连接的主要内容,如果未能解决你的问题,请参考以下文章

oracle学习之基本查询和条件过滤,分组函数使用

oracle之5多行函数之过滤分组函数

Oracle Day3 多行函数多表查询

Oracle数据库从入门到精通-分组统计查询

Oracle数据库,模糊查询去重查询

十MySQL 聚合函数分组查询及过滤分组