1. 程式人生 > >MySQL 之分組查詢

MySQL 之分組查詢

分組查詢

語法:

select 查詢列表
from 表
【where 篩選條件】
group by 分組的欄位
【order by 排序的欄位】;

特點:

  • 1、和分組函式一同查詢的欄位必須是group by後出現的欄位
  • 2、篩選分為兩類:分組前篩選和分組後篩選
針對的表     位置 連線的關鍵字
分組前篩選 原始表 group by前 where
分組後篩選 group by後的結果集 group by後 having

          問題1:分組函式做篩選能不能放在where後面
          答:不能

          問題2:where——group by——having

           一般來講,能用分組前篩選的,儘量使用分組前篩選,提高效率

  • 3、分組可以按單個欄位也可以按多個欄位
  • 4、可以搭配著排序使用

引入:查詢每個部門的員工個數

mysql> SELECT COUNT(*), department_id
    -> FROM employees
    -> GROUP BY department_id;
+----------+---------------+
| COUNT(*) | department_id |
+----------+---------------+
|        1 |          NULL |
|        1 |            10 |
|        2 |            20 |
|        6 |            30 |
|        1 |            40 |
|       45 |            50 |
|        5 |            60 |
|        1 |            70 |
|       34 |            80 |
|        3 |            90 |
|        6 |           100 |
|        2 |           110 |
+----------+---------------+
12 rows in set (0.00 sec)

1.簡單的分組

案例1:查詢每個工種的員工平均工資

mysql> SELECT AVG(salary), job_id
    -> FROM employees
    -> GROUP BY job_id;
+--------------+------------+
| AVG(salary)  | job_id     |
+--------------+------------+
|  8300.000000 | AC_ACCOUNT |
| 12000.000000 | AC_MGR     |
|  4400.000000 | AD_ASST    |
| 24000.000000 | AD_PRES    |
| 17000.000000 | AD_VP      |
|  7920.000000 | FI_ACCOUNT |
| 12000.000000 | FI_MGR     |
|  6500.000000 | HR_REP     |
|  5760.000000 | IT_PROG    |
| 13000.000000 | MK_MAN     |
|  6000.000000 | MK_REP     |
| 10000.000000 | PR_REP     |
|  2780.000000 | PU_CLERK   |
| 11000.000000 | PU_MAN     |
| 12200.000000 | SA_MAN     |
|  8350.000000 | SA_REP     |
|  3215.000000 | SH_CLERK   |
|  2785.000000 | ST_CLERK   |
|  7280.000000 | ST_MAN     |
+--------------+------------+
19 rows in set (0.00 sec)

2、可以實現分組前的篩選

案例1:查詢郵箱中包含a字元的 每個部門的最高工資

mysql> SELECT MAX(salary), department_id, email
    -> FROM employees
    -> WHERE email LIKE '%a%'
    -> GROUP BY department_id;
+-------------+---------------+----------+
| MAX(salary) | department_id | email    |
+-------------+---------------+----------+
|     7000.00 |          NULL | KGRANT   |
|     4400.00 |            10 | JWHALEN  |
|    13000.00 |            20 | MHARTSTE |
|    11000.00 |            30 | DRAPHEAL |
|     6500.00 |            40 | SMAVRIS  |
|     8200.00 |            50 | AFRIPP   |
|     9000.00 |            60 | AHUNOLD  |
|    10000.00 |            70 | HBAER    |
|    13500.00 |            80 | KPARTNER |
|    17000.00 |            90 | NKOCHHAR |
|     9000.00 |           100 | DFAVIET  |
+-------------+---------------+----------+
11 rows in set (0.00 sec)

案例2:查詢有獎金的每個領導手下員工的平均工資

mysql> SELECT AVG(salary), manager_id
    -> FROM employees
    -> WHERE commission_pct IS NOT NULL
    -> GROUP BY manager_id;
+--------------+------------+
| AVG(salary)  | manager_id |
+--------------+------------+
| 12200.000000 |        100 |
|  8500.000000 |        145 |
|  8500.000000 |        146 |
|  7766.666667 |        147 |
|  8650.000000 |        148 |
|  8333.333333 |        149 |
+--------------+------------+
6 rows in set (0.00 sec)

3、分組後篩選

案例:查詢哪個部門的員工個數>5,步驟如下所示:

  • ①查詢每個部門的員工個數
mysql> SELECT COUNT(*),department_id
    -> FROM employees
    -> GROUP BY department_id;
+----------+---------------+
| COUNT(*) | department_id |
+----------+---------------+
|        1 |          NULL |
|        1 |            10 |
|        2 |            20 |
|        6 |            30 |
|        1 |            40 |
|       45 |            50 |
|        5 |            60 |
|        1 |            70 |
|       34 |            80 |
|        3 |            90 |
|        6 |           100 |
|        2 |           110 |
+----------+---------------+
12 rows in set (0.00 sec)
  • ② 篩選剛才①結果
mysql> SELECT COUNT(*),department_id
    -> FROM employees
    -> GROUP BY department_id
    -> HAVING COUNT(*)>5;
+----------+---------------+
| COUNT(*) | department_id |
+----------+---------------+
|        6 |            30 |
|       45 |            50 |
|       34 |            80 |
|        6 |           100 |
+----------+---------------+
4 rows in set (0.00 sec)

案例2:每個工種有獎金的員工的最高工資>10000的工種編號和最高工資

mysql> SELECT MAX(salary) AS max_salary, job_id
    -> FROM employees
    -> WHERE commission_pct IS NOT NULL
    -> GROUP BY job_id
    -> HAVING max_salary > 10000;
+------------+--------+
| max_salary | job_id |
+------------+--------+
|   14000.00 | SA_MAN |
|   11500.00 | SA_REP |
+------------+--------+
2 rows in set (0.00 sec)

案例3:領導編號>102的每個領導手下的最低工資大於5000的領導編號和最低工資

mysql> SELECT MIN(salary) min_salary, manager_id
    -> FROM employees
    -> WHERE manager_id > 102
    -> GROUP BY manager_id
    -> HAVING min_salary > 5000;
+------------+------------+
| min_salary | manager_id |
+------------+------------+
|    6900.00 |        108 |
|    7000.00 |        145 |
|    7000.00 |        146 |
|    6200.00 |        147 |
|    6100.00 |        148 |
|    6200.00 |        149 |
|    6000.00 |        201 |
|    8300.00 |        205 |
+------------+------------+
8 rows in set (0.00 sec)

4.新增排序

案例:每個工種有獎金的員工的最高工資>6000的工種編號和最高工資,按最高工資升序;

mysql> SELECT job_id, MAX(salary) max_salary
    -> FROM employees
    -> WHERE commission_pct IS NOT NULL
    -> GROUP BY job_id
    -> HAVING max_salary > 6000
    -> ORDER BY max_salary DESC;
+--------+------------+
| job_id | max_salary |
+--------+------------+
| SA_MAN |   14000.00 |
| SA_REP |   11500.00 |
+--------+------------+
2 rows in set (0.00 sec)

5.按多個欄位分組

案例:查詢每個工種每個部門的最低工資,並按最低工資降序

mysql> SELECT MIN(salary) min_salary, job_id, department_id
    -> FROM employees
    -> GROUP BY job_id, department_id
    -> ORDER BY min_salary DESC;
+------------+------------+---------------+
| min_salary | job_id     | department_id |
+------------+------------+---------------+
|   24000.00 | AD_PRES    |            90 |
|   17000.00 | AD_VP      |            90 |
|   13000.00 | MK_MAN     |            20 |
|   12000.00 | AC_MGR     |           110 |
|   12000.00 | FI_MGR     |           100 |
|   11000.00 | PU_MAN     |            30 |
|   10500.00 | SA_MAN     |            80 |
|   10000.00 | PR_REP     |            70 |
|    8300.00 | AC_ACCOUNT |           110 |
|    7000.00 | SA_REP     |          NULL |
|    6900.00 | FI_ACCOUNT |           100 |
|    6500.00 | HR_REP     |            40 |
|    6100.00 | SA_REP     |            80 |
|    6000.00 | MK_REP     |            20 |
|    5800.00 | ST_MAN     |            50 |
|    4400.00 | AD_ASST    |            10 |
|    4200.00 | IT_PROG    |            60 |
|    2500.00 | SH_CLERK   |            50 |
|    2500.00 | PU_CLERK   |            30 |
|    2100.00 | ST_CLERK   |            50 |
+------------+------------+---------------+
20 rows in set (0.00 sec)