Bootstrap

SQL查询语句分步详解——SELECT...FROM...WHERE...GROUP BY...

GROUP BY : 分组查询命令

        1.书写顺序:

                     SELECT 字段名,函数,子查询

                     FROM 表名

                     WHERE 定位数据行条件

                     GROUP BY 分组字段

 

          2.执行顺序:

                     FROM-->WHERE-->GROUP BY-->SELECT

 

                     *****如果同时出现WHERE与GROUP BY;GROUP BY应该在where之后执行*****

 

          3.执行原理:

             GROUP BY 执行时首先根据分组字段数据种类,对临时表数据行进行分类。然后将具有相同特征的数据行读取出来保存到一个全新临时表

           4.七个查询命令中,只有GROUP BY有机会在执行完毕后,一次生成多个临时表。

 

     【重要结论:在一条select语句中,如果有group by语句的话,

                                select后面只能跟:参加分组的字段以及分组函数,其它的一律不能写。】

    原因:select与group by联合使用时,只会读取当前临时表下指定字段下的【第一个数据】,此时

                  select所抓取数据应该是当前临时表所有数据行【公有的特征】,所以此时select抓取的字

                  段,就应该是group by进行分组的字段。

 

硬盘上EMP.frm

EMPNO

ENAME

JOB

MGR

HIREDATE

SAL

COMM

DEPTNO

7369

SMITH

CLERK

7902

1980/12/17

800

NULL

20

7499

ALLEN

SALESMAN

7698

1981/2/20

1600

300

30

7521

WARD

SALESMAN

7698

1981/2/22

1250

500

30

7566

JONES

MANAGER

7839

1981/4/2

2975

NULL

20

7654

MARTIN

SALESMAN

7698

1981/9/28

1250

1400

30

7698

BLAKE

MANAGER

7839

1981/5/1

2850

NULL

30

7782

CLARK

MANAGER

7839

1981/6/9

2450

NULL

10

7788

SCOTT

ANALYST

7566

1987/4/19

3000

NULL

20

7839

KING

PRESIDENT

1981/11/17

5000

NULL

10

7844

TURNER

SALESMAN

7698

1981/9/8

1500

0

30

7876

ADAMS

CLERK

7788

1987/5/23

1100

NULL

20

7900

JAMES

CLERK

7698

1981/12/3

950

NULL

30

7902

FORD

ANALYST

7566

1981/12/3

3000

NULL

20

7934

MILLER

CLERK

7782

1982/1/23

1300

NULL

10

需求:查询部门30下所有职位的人数

SQL:

     SELECT

             JOB,COUNT(*)

     FROM  

             EMP

     WHERE 

             DEPTNO = 30

     GROUP  BY

             JOB

第一步:执行  FROM EMP

           该命令的执行会在内存中生成一个与源表一样的临时表(第一个临时表)

 

第一个临时表

EMPNO

ENAME

JOB

MGR

HIREDATE

SAL

COMM

DEPTNO

7369

SMITH

CLERK

7902

1980/12/17

800

NULL

20

7499

ALLEN

SALESMAN

7698

1981/2/20

1600

300

30

7521

WARD

SALESMAN

7698

1981/2/22

1250

500

30

7566

JONES

MANAGER

7839

1981/4/2

2975

NULL

20

7654

MARTIN

SALESMAN

7698

1981/9/28

1250

1400

30

7698

BLAKE

MANAGER

7839

1981/5/1

2850

NULL

30

7782

CLARK

MANAGER

7839

1981/6/9

2450

NULL

10

7788

SCOTT

ANALYST

7566

1987/4/19

3000

NULL

20

7839

KING

PRESIDENT

1981/11/17

5000

NULL

10

7844

TURNER

SALESMAN

7698

1981/9/8

1500

0

30

7876

ADAMS

CLERK

7788

1987/5/23

1100

NULL

20

7900

JAMES

CLERK

7698

1981/12/3

950

NULL

30

7902

FORD

ANALYST

7566

1981/12/3

3000

NULL

20

7934

MILLER

CLERK

7782

1982/1/23

1300

NULL

10

第二步:执行   WHERE DEPTNO = 30

          

           1.对第一个临时表进行遍历;循环遍历时,对DEPTNO = 30 (也就是部门编号=30)的数据行进行定位。

     2.循环遍历结束后,将满足定位条件的数据行读取出来,生成一个全新的临时表(第二个临时表),第二个临时表生成后,第一个临时表被销毁。

第二个临时表

EMPNO

ENAME

JOB

MGR

HIREDATE

SAL

COMM

DEPTNO

7499

ALLEN

SALESMAN

7698

1981/2/20

1600

300

30

7521

WARD

SALESMAN

7698

1981/2/22

1250

500

30

7654

MARTIN

SALESMAN

7698

1981/9/28

1250

1400

30

7698

BLAKE

MANAGER

7839

1981/5/1

2850

NULL

30

7844

TURNER

SALESMAN

7698

1981/9/8

1500

0

30

7900

JAMES

CLERK

7698

1981/12/3

950

NULL

30

第三步:执行 GROUP BY JOB

        1. 对第二个临时表JOB字段下数据种类进行统计(统计出多少种,就会生成多少个临时表)。

        2. 将具有相同特征的数据行保存到同一个临时表。这些临时表全部生成后,前面由WHERE命令生成的临时表(这里是第二个临时表)就会被销毁。

 

第三个临时表

EMPNO

ENAME

JOB

MGR

HIREDATE

SAL

COMM

DEPTNO

7499

ALLEN

SALESMAN

7698

1981/2/20

1600

300

30

7521

WARD

SALESMAN

7698

1981/2/22

1250

500

30

7654

MARTIN

SALESMAN

7698

1981/9/28

1250

1400

30

7844

TURNER

SALESMAN

7698

1981/9/8

1500

0

30

 

第四个临时表

EMPNO

ENAME

JOB

MGR

HIREDATE

SAL

COMM

DEPTNO

7698

BLAKE

MANAGER

7839

1981/5/1

2850

NULL

30

 

第五个临时表

EMPNO

ENAME

JOB

MGR

HIREDATE

SAL

COMM

DEPTNO

7900

JAMES

CLERK

7698

1981/12/3

950

NULL

30

第四步:执行 SELECT JOB,COUNT(*)

           SELECT 执行原理:

                 1.SELECT执行特点与提供临时表的命令有关。

                 2.如果临时表由【FROM】或则【WHERE】提供,此时SELECT面对只有一个临时表。此时SELECT将

                         指定字段下所有内容读取出来生成一个全新的临时表。

                 3.如果临时表由【group by】提供,此时SELECT可能面对多个临时表。

                       1)SELECT将依次操作每一个临时表

                       2)SELECT在操作某个临时表时,只会读取【指定字段下第一个数据】

                       3)SELECT将从多个临时表读取数据合成一列保存到一个全新的临时表中

            根据SELECT命令的执行原理,这里执行SELECT JOB,COUNT(*)命令时将会对刚刚生成的三个临时表(也就是第三个、第四个、第五个临时表)进行操作。然后生成一个全新的临时表(也就是第六个临时表)。

第六个临时表

JOB

count(*)

SALESMAN

4

MANAGER

1

CLERK

1

当第六个临时表生成后,由前一个命令生成的第三个、第四个和第五个临时表会被销毁。此时MySQL服务器就会把第六个临时表作为最终的结果推送给客户端,供操作者查阅。

;