MySQL——分組函數、distinct、分組查詢、鏈接查詢、子查詢

博客目錄

一、分組函數
二、distinct
三、分組查詢(group by、having)
四、一個完整的DQL語句的總結
五、鏈接查詢(跨表查詢)(關聯多個表查詢)
六、子查詢

1、分組函數

一、 會自動忽略空值

二、 分組函數不能直接使用在where關鍵字後面

  • 取平均值:avgmysql

    mysql> select avg(sal) from emp;
    +-------------+
    | avg(sal)    |
    +-------------+
    | 2073.214286 |
    +-------------+
    1 row in set (0.60 sec)
  • 最大值:maxweb

  • 最小值:min
  • 取記錄數:count sql

    mysql> select count(sal) from emp;
    +------------+
    | count(sal) |
    +------------+
    |         14 |
    +------------+
    1 row in set (0.04 sec)
  • 求和:sum

2、distinct(去除重複記錄)(顯示)

使用distinct須要注意

一、該關鍵字前面不能出現字段
二、該關鍵字只能出如今全部字段的最前面

mysql> select distinct job from emp;svg

+-----------+
| job       |
+-----------+
| CLERK     |
| SALESMAN  |
| MANAGER   |
| ANALYST   |
| PRESIDENT |
+-----------+
5 rows in set (0.09 sec)

統計公司一共有幾個工做崗位函數

mysql> select count(distinct job) from emp;
+---------------------+
| count(distinct job) |
+---------------------+
|                   5 |
+---------------------+
1 row in set (0.00 sec)

3、分組查詢(group by、having)

一、group by

經過哪一個或者哪些字段進行分組code

重點

若一條DQL語句中有group by子句,那麼select關鍵字後面只能跟參與分組的字段和分組函數(好比ename這些是不能夠的,不是分組字段)router

一、找出每一個工做崗位的最高薪水xml

分析:先按照工做崗位分組,再使用max求每組最高記錄排序

mysql> select job,max(sal) from emp group by job;
    +-----------+----------+
    | job       | max(sal) |
    +-----------+----------+
    | ANALYST   |  3000.00 |
    | CLERK     |  1300.00 |
    | MANAGER   |  2975.00 |
    | PRESIDENT |  5000.00 |
    | SALESMAN  |  1600.00 |
    +-----------+----------+
    5 rows in set (0.00 sec)

二、計算每一個部門的平均薪水ip

mysql> select
    -> deptno,avg(sal) as avgsal
    -> from
    -> emp
    -> group by
    -> deptno;
+--------+-------------+
| deptno | avgsal      |
+--------+-------------+
|     10 | 2916.666667 |
|     20 | 2175.000000 |
|     30 | 1566.666667 |
+--------+-------------+
3 rows in set (0.00 sec)

三、計算不一樣工做崗位的最高薪水

mysql> select
    -> deptno,job,avg(sal) as avgsal
    -> from
    -> emp
    -> group by
    -> deptno,job;
+--------+-----------+-------------+
| deptno | job       | avgsal      |
+--------+-----------+-------------+
|     10 | CLERK     | 1300.000000 |
|     10 | MANAGER   | 2450.000000 |
|     10 | PRESIDENT | 5000.000000 |
|     20 | ANALYST   | 3000.000000 |
|     20 | CLERK     |  950.000000 |
|     20 | MANAGER   | 2975.000000 |
|     30 | CLERK     |  950.000000 |
|     30 | MANAGER   | 2850.000000 |
|     30 | SALESMAN  | 1400.000000 |
+--------+-----------+-------------+
9 rows in set (0.04 sec)

二、having

  1. having和where功能都是爲了完成數據的過濾
  2. where和having後面都是添加條件
  3. where和group by以前完成過濾
  4. having在group by以後完成過濾

找出每一個工做崗位的最高薪水,除manager以外

mysql> select
    -> job,avg(sal)
    -> from
    -> emp
    -> group by
    -> job
    -> having
    -> avg(sal)>1500;
+-----------+-------------+
| job       | avg(sal)    |
+-----------+-------------+
| ANALYST   | 3000.000000 |
| MANAGER   | 2758.333333 |
| PRESIDENT | 5000.000000 |
+-----------+-------------+
3 rows in set (0.09 sec)

注意上面爲何不能用where,由於where關鍵字後面不能用分組函數,分組函數必須在分組完成後執行,而分組要group by。而group by在where後執行

原則

通常狀況儘可能在where中過濾,實在沒法過濾的數據,一般是須要先分組以後再過濾,此時能夠選擇having,這牽扯到效率問題


4、一個完整的DQL語句的總結

select   
    ...
from    從某張表中檢索數據
    ...
where   通過某條件進行過濾
    ...
group by    分組
    ...
having      分組以後不滿意再過濾
    ...
order by    排序輸出
    ...

以上關鍵字順序不能改變,嚴格遵照

如下是執行順序

一、from
二、where
三、group by
四、having
五、select
六、order by


5、鏈接查詢(跨表查詢)(關聯多個表查詢)

一、鏈接查詢分類(年代)

  • SQL92
  • SQL99

二、鏈接查詢根據鏈接方式分類

  • 內鏈接(兩張表在進行錶鏈接的時候,鏈接記錄百分百匹配記錄可查,內鏈接只能是兩表匹配的)
    • 等值鏈接
    • 非等值鏈接
    • 自鏈接
  • 外連接(兩表進行外鏈接的時候,除了能夠百分百記錄查詢,另外須要將其中任意一張表數據無條件的所有展現出來,就要使用外鏈接)
    • 左外鏈接(左鏈接):將左邊數據所有顯示
    • 右外鏈接(右鏈接):將右邊數據所有顯示
  • 全鏈接

外鏈接的查詢結果都是一直大於等於內鏈接的查詢結果

三、當多張表進行鏈接查詢,若沒有任何條件進行限制,會發生什麼現象

會發生總記錄是兩張表記錄乘積(此現象是笛卡爾積現象,爲了不該現象發生,必須在錶鏈接時候加上限制)

一、內鏈接(等值鏈接)—————查詢每一個員工所在的部門名稱,要求最終顯示員工名和對應的部門名(兩張表:員工表(部門號)、部門表(部門號))

tip:在鏈接查詢的時候雖然使用了限制條件,可是匹配的次數沒有減小,仍是與無限制同樣,只是此次的結果都是有效記錄
  • SQL92語法:(屬於內鏈接中的等值鏈接)(缺點:錶鏈接與過濾同時了,結構不清晰)

    mysql> select
        -> e.ename,d.dname
        -> from
        -> emp e,dept d
        -> where
        -> e.deptno=d.deptno;
    +--------+------------+
    | ename  | dname      |
    +--------+------------+
    | CLARK  | ACCOUNTING |
    | KING   | ACCOUNTING |
    | MILLER | ACCOUNTING |
    | SMITH  | RESEARCH   |
    | JONES  | RESEARCH   |
    | SCOTT  | RESEARCH   |
    | ADAMS  | RESEARCH   |
    | FORD   | RESEARCH   |
    | ALLEN  | SALES      |
    | WARD   | SALES      |
    | MARTIN | SALES      |
    | BLAKE  | SALES      |
    | TURNER | SALES      |
    | JAMES  | SALES      |
    +--------+------------+
    14 rows in set (0.15 sec)
  • SQL99語法(inner能夠省略)(好處:錶鏈接與過濾分離,在最後加where便可過濾,結構清晰)

    mysql> select
        -> e.ename,d.dname
        -> from
        -> emp e
        -> inner join
        -> dept d
        -> on
        -> e.deptno=d.deptno;
    +--------+------------+
    | ename  | dname      |
    +--------+------------+
    | CLARK  | ACCOUNTING |
    | KING   | ACCOUNTING |
    | MILLER | ACCOUNTING |
    | SMITH  | RESEARCH   |
    | JONES  | RESEARCH   |
    | SCOTT  | RESEARCH   |
    | ADAMS  | RESEARCH   |
    | FORD   | RESEARCH   |
    | ALLEN  | SALES      |
    | WARD   | SALES      |
    | MARTIN | SALES      |
    | BLAKE  | SALES      |
    | TURNER | SALES      |
    | JAMES  | SALES      |
    +--------+------------+
    14 rows in set (0.00 sec)

二、內鏈接(非等值鏈接,SQL99)————找出每個員工對應的工資等級,要求顯示員工名,工資,工資等級(兩張表:員工表,工資等級表(salgrade))

mysql> select
    -> e.ename,e.sal,s.grade
    -> from
    -> emp e
    -> join
    -> salgrade s
    -> on
    -> e.sal
    -> between
    -> s.losal
    -> and
    -> s.hisal;
+--------+---------+-------+
| ename  | sal     | grade |
+--------+---------+-------+
| SMITH  |  800.00 |     1 |
| ALLEN  | 1600.00 |     3 |
| WARD   | 1250.00 |     2 |
| JONES  | 2975.00 |     4 |
| MARTIN | 1250.00 |     2 |
| BLAKE  | 2850.00 |     4 |
| CLARK  | 2450.00 |     4 |
| SCOTT  | 3000.00 |     4 |
| KING   | 5000.00 |     5 |
| TURNER | 1500.00 |     3 |
| ADAMS  | 1100.00 |     1 |
| JAMES  |  950.00 |     1 |
| FORD   | 3000.00 |     4 |
| MILLER | 1300.00 |     2 |
+--------+---------+-------+
14 rows in set (0.03 sec)

三、內鏈接(自鏈接,SQL99)——找出每一個員工的上級領導,要求顯示員工名以及對應的領導名(一張表當作兩張表)

如下是員工表,表中也有員工序號和對應上級的序號,便可看出兩張表

mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO
+-------+--------+-----------+------+------------+---------+---------+--------
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10
+-------+--------+-----------+------+------------+---------+---------+--------
14 rows in set (0.00 sec)



mysql> select
    -> a.ename as empname,b.ename as leadername
    -> from
    -> emp a
    -> join
    -> emp b
    -> on
    -> a.mgr=b.empno;
+---------+------------+
| empname | leadername |
+---------+------------+
| SMITH   | FORD       |
| ALLEN   | BLAKE      |
| WARD    | BLAKE      |
| JONES   | KING       |
| MARTIN  | BLAKE      |
| BLAKE   | KING       |
| CLARK   | KING       |
| SCOTT   | JONES      |
| TURNER  | BLAKE      |
| ADAMS   | SCOTT      |
| JAMES   | BLAKE      |
| FORD    | JONES      |
| MILLER  | CLARK      |
+---------+------------+
13 rows in set (0.00 sec)

SQL92語法就是將join改爲’,’,on改爲where

四、外鏈接(右鏈接)——找出每一個員工對應的部門名稱,要求部門名稱所有顯示(部分多出來的記錄將用null與其匹配)(左鏈接的話將dept和emp換個位置就好)

mysql> select
    -> e.ename,d.dname
    -> from
    -> emp e
    -> right outer join
    -> dept d
    -> on
    -> e.deptno=d.deptno;
+--------+------------+
| ename  | dname      |
+--------+------------+
| CLARK  | ACCOUNTING |
| KING   | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH  | RESEARCH   |
| JONES  | RESEARCH   |
| SCOTT  | RESEARCH   |
| ADAMS  | RESEARCH   |
| FORD   | RESEARCH   |
| ALLEN  | SALES      |
| WARD   | SALES      |
| MARTIN | SALES      |
| BLAKE  | SALES      |
| TURNER | SALES      |
| JAMES  | SALES      |
| NULL   | OPERATIONS |
+--------+------------+
15 rows in set (0.05 sec)

五、找出每一個員工對應的領導名,要求顯示全部的員工

mysql> select a.ename empname,b.ename leadername from emp a join emp b on a.mgr=
b.empno;
+---------+------------+
| empname | leadername |
+---------+------------+
| SMITH   | FORD       |
| ALLEN   | BLAKE      |
| WARD    | BLAKE      |
| JONES   | KING       |
| MARTIN  | BLAKE      |
| BLAKE   | KING       |
| CLARK   | KING       |
| SCOTT   | JONES      |
| TURNER  | BLAKE      |
| ADAMS   | SCOTT      |
| JAMES   | BLAKE      |
| FORD    | JONES      |
| MILLER  | CLARK      |
+---------+------------+
13 rows in set (0.00 sec)

(多張表)六、找出每一個員工對應的部門名稱,以及該員工對應的部門名稱,工資等級。要求顯示員工名、部門名、工資等級

多張表進行錶鏈接的語法格式(a,b,c表)
原理:a與b鏈接後,再a與c鏈接

select
    ...
from 
    a
join
    b
on
    條件
join
    c
on
    條件;

mysql> select e.ename,d.dname,s.grade from emp e join dept d on e.deptno=d.deptn
o join salgrade s on e.sal between s.losal and s.hisal;
+--------+------------+-------+
| ename  | dname      | grade |
+--------+------------+-------+
| SMITH  | RESEARCH   |     1 |
| ALLEN  | SALES      |     3 |
| WARD   | SALES      |     2 |
| JONES  | RESEARCH   |     4 |
| MARTIN | SALES      |     2 |
| BLAKE  | SALES      |     4 |
| CLARK  | ACCOUNTING |     4 |
| SCOTT  | RESEARCH   |     4 |
| KING   | ACCOUNTING |     5 |
| TURNER | SALES      |     3 |
| ADAMS  | RESEARCH   |     1 |
| JAMES  | SALES      |     1 |
| FORD   | RESEARCH   |     4 |
| MILLER | ACCOUNTING |     2 |
+--------+------------+-------+
14 rows in set (0.05 sec)

TIP

爲何inner、outer能夠省略

由於區份內鏈接和外鏈接依靠的不是這些關鍵字,而是看SQL語句中是否存在left/right,若存在,標識必定是個外鏈接,其餘都是內鏈接

inner、outer加上有什麼好處

加強可讀性


6、子查詢

子查詢就是嵌套的select語句(select語句嵌套select語句)

一、子查詢出現的位置

  • select…(select)
  • from…(select)
  • where…(select)

where後使用子查詢

找出薪水比公司平均薪水高的員工,要求顯示員工名和薪水

  • 第一步找出公司的平均水平

    select avg(sal) from emp;
  • 第二步找出薪水大於平均薪水的員工信息

    mysql> select ename,sal from emp where sal>(select avg(sal) from emp);
    +-------+---------+
    | ename | sal     |
    +-------+---------+
    | JONES | 2975.00 |
    | BLAKE | 2850.00 |
    | CLARK | 2450.00 |
    | SCOTT | 3000.00 |
    | KING  | 5000.00 |
    | FORD  | 3000.00 |
    +-------+---------+
    6 rows in set (0.00 sec)
from後面使用子查詢(可將查詢結果當作臨時表)

找出每一個部門的平均薪水,並找出平均薪水的薪水等級

  • 第一步找出每一個部門的平均薪水

    mysql> select avg(sal) as avgsal from emp group by deptno;
  • 第二步將上面的查詢結果當作臨時表t,t表和salgrade s表進行錶鏈接,條件:t.avgsal between s.losal and s.hisal

    mysql> select
        -> t.deptno,t.avgsal,s.grade
        -> from
        -> (select deptno,avg(sal) as avgsal from emp group by deptno) t
        -> join
        -> salgrade s
        -> on
        -> t.avgsal
        -> between
        -> s.losal
        -> and
        -> s.hisal;
    +--------+-------------+-------+
    | deptno | avgsal      | grade |
    +--------+-------------+-------+
    |     30 | 1566.666667 |     3 |
    |     10 | 2916.666667 |     4 |
    |     20 | 2175.000000 |     4 |
    +--------+-------------+-------+
    3 rows in set (0.12 sec)
select後使用子查詢(瞭解)

顯示員工名與其對應的部門名

mysql> select e.ename,(select d.dname from dept d where e.deptno=d.deptno) as dn
ame from emp e;
+--------+------------+
| ename  | dname      |
+--------+------------+
| SMITH  | RESEARCH   |
| ALLEN  | SALES      |
| WARD   | SALES      |
| JONES  | RESEARCH   |
| MARTIN | SALES      |
| BLAKE  | SALES      |
| CLARK  | ACCOUNTING |
| SCOTT  | RESEARCH   |
| KING   | ACCOUNTING |
| TURNER | SALES      |
| ADAMS  | RESEARCH   |
| JAMES  | SALES      |
| FORD   | RESEARCH   |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.00 sec)