多字段分组规则: 1.多字段分组时,分组字段出现顺序对于最终查询结果没有任何影响的。 group by deptno,job 与 group by job,deptno查询最终结果是一致的 2.多字段分组时,GROUP BY一次只能根据一个分组字段进行分组 GROUP BY DEPTNO,JOB ,此时GORUP BY需要执行两次 3.多字段分组时,从第二个分组字段开始,操作的是上一个分组字段生成的临时表。 GROUP BY DEPTNO,JOB.当执行group by job时,操作的临时表是由group by deptno生成的。 |
| | | | 硬盘上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 | |
需求:查询每个部门下各个职位的人数 SQL: SELECT DEPTNO,JOB,COUNT(*) FROM EMP GROUP BY DEPTNO,JOB #多字段分组(当前分组字段是两个分别是:DEPTNO和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 | |
第二步:执行 GROUP BY DEPTNO 1. 对第一个临时表DEPTNO字段下数据种类进行统计(当前临时表中DEPTNO字段下有3个不同的数据,分别是10、20和30,为此该命令执行完成后就会生成3个临时表)。 2. 将具有相同特征的数据行保存到同一个临时表。这些临时表全部生成后,前面由WHERE命令生成的临时表 (这里是第二个临时表)就会被销毁。 |
| | | | 第二个临时表 | | | | EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | 7369 | SMITH | CLERK | 7902 | 1980/12/17 | 800 | NULL | 20 | 7566 | JONES | MANAGER | 7839 | 1981/4/2 | 2975 | NULL | 20 | 7788 | SCOTT | ANALYST | 7566 | 1987/4/19 | 3000 | NULL | 20 | 7876 | ADAMS | CLERK | 7788 | 1987/5/23 | 1100 | NULL | 20 | 7902 | FORD | ANALYST | 7566 | 1981/12/3 | 3000 | NULL | 20 | |
| | | | 第三个临时表 | | | | 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 | |
| | | | 第四个临时表 | | | | EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | 7782 | CLARK | MANAGER | 7839 | 1981/6/9 | 2450 | NULL | 10 | 7839 | KING | PRESIDENT | | 1981/11/17 | 5000 | NULL | 10 | 7934 | MILLER | CLERK | 7782 | 1982/1/23 | 1300 | NULL | 10 | |
第三步:执行 group by job 该命令操作第二步生成三个临时表,需要依次对三个临时表在进行拆分 1.对每个临时表中的JOB字段下的数据进行统计, 第二个临时表JOB字段下有三个不同的数据(分别是:CLERK、MANAGER和ANALYST),为此第二个临时表会生成三个 全新的临时表,新的临时表生成后,第二个临时表就会被销毁。 第三个临时表JOB字段下也有三个不同的数据(分别是:SALESMAN、MANAGER和CLERK),为此第三个临时表也会生成三个全新的临时表,新的临时表生成之后,第三个临时表被销毁。 同样的原理,第四个临时表也会生成三个全新的临时表,新的临时表生成之后,第四个临时表被销毁。 |
由第二个临时表生成的第五个临时表 EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | 7369 | SMITH | CLERK | 7902 | 1980/12/17 | 800 | NULL | 20 | 7876 | ADAMS | CLERK | 7788 | 1987/5/23 | 1100 | NULL | 20 | |
由第二个临时表生成的第七个临时表 EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | 7566 | JONES | MANAGER | 7839 | 1981/4/2 | 2975 | NULL | 20 | |
由第二个临时表生成的第七个临时表 EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | 7788 | SCOTT | ANALYST | 7566 | 1987/4/19 | 3000 | NULL | 20 | 7902 | FORD | ANALYST | 7566 | 1981/12/3 | 3000 | NULL | 20 | |
由第三个临时表生成的第八个临时表 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 | |
由第四个临时表生成的第十一个临时表 EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | 7782 | CLARK | MANAGER | 7839 | 1981/6/9 | 2450 | NULL | 10 | |
由第四个临时表生成的第十二个临时表 EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | 7839 | KING | PRESIDENT | | 1981/11/17 | 5000 | NULL | 10 | |
由第四个临时表生成的第十三个临时表 EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | 7934 | MILLER | CLERK | 7782 | 1982/1/23 | 1300 | NULL | 10 | |
第四步:执行 SELECT DEPTNO JOB COUNT(*) 由于SELECT 操作的临时表是由group by提供的多个临时表,SELECT将依次对每个临时表进行操作,它是读取相应字段下的第一个数据,将它们对应的字段合并成一列保存到一个新的临时表中。 |
DEPTNO | JOB | COUNT(*) | 10 | MANAGER | 1 | 10 | PRESIDENT | 1 | 10 | CLERK | 1 | 20 | CLERK | 2 | 20 | MANAGER | 1 | 20 | ANALYST | 2 | 30 | SALESMAN | 4 | 30 | MANAGER | 1 | 30 | CLERK | 1 | |
全新的临时表生成之后,由group by命令生成的所有临时表都会被销毁,最后MySQL服务器将最后生成的临时表推送给客户端,供操作者查阅。 |
|