SQL-DQL(6)之分组查询

语法:

select 分组函数(),列(要求出现在group by 后面的字段)(5)
from 表 (1)
【where 筛选条件】(2)
group by 分组列表 (3)
【having分组后的筛选】(4)
【order by 排序字段】(6)
#(1),(2),(3),(4),(5),(6)为执行顺序。

注意:

  1.查询列表必须要是在分组函数和group by 后出现的字段。
  2.分组查询中的筛选条件分为两种(能用分组前筛选的,就优先考虑使用分组前筛选。
                  数据源       位置                关键字
    分组前筛选     原始表        group by子句前面    where
    分组后的筛选   分组后的结果集  group by子句后面    having
  3.group by 子句支持单个字段分组,多个字段分组(多个字段用逗号隔开,没有顺序要求),表达式,函数,别名(当使用别名时,要全部使用别名),也可以添加排序。

√一. 简单分组查询练习

mysql> #1. 查询每个部门的评价工资
mysql> select avg(salary) 平均工资, department_id from employees group by department_id;
+--------------+---------------+
| 平均工资     | department_id |
+--------------+---------------+
|  7000.000000 |          NULL |
|  4400.000000 |            10 |
|  9500.000000 |            20 |
|  4150.000000 |            30 |
|  6500.000000 |            40 |
|  3475.555556 |            50 |
|  5760.000000 |            60 |
| 10000.000000 |            70 |
|  8955.882353 |            80 |
| 19333.333333 |            90 |
|  8600.000000 |           100 |
| 10150.000000 |           110 |
+--------------+---------------+
12 rows in set (0.02 sec)

#2. 查询每个位置上的部门个数。
mysql> select count(*) 部门个数, location_id from departments group by location_id;
+--------------+-------------+
| 部门个数     | location_id |
+--------------+-------------+
|            1 |        1400 |
|            1 |        1500 |
|           21 |        1700 |
|            1 |        1800 |
|            1 |        2400 |
|            1 |        2500 |
|            1 |        2700 |
+--------------+-------------+
7 rows in set (0.07 sec)


mysql> #3.查询每个工种的最高工资

mysql> select max(salary) 最高工资, job_id from employees group by job_id;
+--------------+------------+
| 最高工资     | job_id     |
+--------------+------------+
|      8300.00 | AC_ACCOUNT |
|     12000.00 | AC_MGR     |
|      4400.00 | AD_ASST    |
|     24000.00 | AD_PRES    |
|     17000.00 | AD_VP      |
|      9000.00 | FI_ACCOUNT |
|     12000.00 | FI_MGR     |
|      6500.00 | HR_REP     |
|      9000.00 | IT_PROG    |
|     13000.00 | MK_MAN     |
|      6000.00 | MK_REP     |
|     10000.00 | PR_REP     |
|      3100.00 | PU_CLERK   |
|     11000.00 | PU_MAN     |
|     14000.00 | SA_MAN     |
|     11500.00 | SA_REP     |
|      4200.00 | SH_CLERK   |
|      3600.00 | ST_CLERK   |
|      8200.00 | ST_MAN     |
+--------------+------------+
19 rows in set (0.00 sec)

√二. 添加筛选条件分组


mysql> #1. 查询邮箱包含e字符的,每个部门的平均工资
mysql> select avg(salary) 平均工资,department_id from employees where email like '%e%' group by department_id;
+--------------+---------------+
| 平均工资     | department_id |
+--------------+---------------+
|  4400.000000 |            10 |
| 13000.000000 |            20 |
|  6750.000000 |            30 |
|  3221.052632 |            50 |
|  5100.000000 |            60 |
| 10000.000000 |            70 |
|  9781.250000 |            80 |
| 17000.000000 |            90 |
|  9733.333333 |           100 |
|  8300.000000 |           110 |
+--------------+---------------+
10 rows in set (0.09 sec)

注意⚠️当我又想看邮箱是否含有‘e’时,我把字段‘email’也放在查询列表里,然后就报错了因为查询列表必须只能是在分组函数和group by 后出现的字段。

mysql> #2. 查询邮箱包含e字符的,每个部门的平均工资
mysql> select avg(salary) 平均工资,department_id from employees where email like '%e%' group by department_id;
+--------------+---------------+
| 平均工资     | department_id |
+--------------+---------------+
|  4400.000000 |            10 |
| 13000.000000 |            20 |
|  6750.000000 |            30 |
|  3221.052632 |            50 |
|  5100.000000 |            60 |
| 10000.000000 |            70 |
|  9781.250000 |            80 |
| 17000.000000 |            90 |
|  9733.333333 |           100 |
|  8300.000000 |           110 |
+--------------+---------------+
10 rows in set (0.09 sec)

mysql> select avg(salary) 平均工资,department_id,email from employees where email like '%e%' group by department_id;
ERROR 1055 (42000): Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'myemployees.employees.email' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

mysql> #3. 查询有奖金的每个领导手下员工的最高工资

mysql> select max(salary) 最高工资,manager_id from employees where commission_pct is not null group by manager_id;
+--------------+------------+
| 最高工资     | manager_id |
+--------------+------------+
|     14000.00 |        100 |
|     10000.00 |        145 |
|     10000.00 |        146 |
|     10500.00 |        147 |
|     11500.00 |        148 |
|     11000.00 |        149 |
+--------------+------------+
6 rows in set (0.29 sec)

√三. 按表达式/函数/别名分组查询

mysql> #1. 查询员工个数大于2 的部门
mysql> #(1)首先查询出每个部门的员工个数
mysql> select count(*) 员工个数, department_id from employees group by department_id;
+--------------+---------------+
| 员工个数     | 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> #根据(1)的结果进行筛选
mysql> select count(*) 员工个数, department_id from employees group by department_id having 员工个数 >2;
+--------------+---------------+
| 员工个数     | department_id |
+--------------+---------------+
|            6 |            30 |
|           45 |            50 |
|            5 |            60 |
|           34 |            80 |
|            3 |            90 |
|            6 |           100 |
+--------------+---------------+
6 rows in set (0.00 sec)

mysql> #2. 查询每个工种有奖金的员工的最高工资> 12000的工种号和最高工资
mysql> select job_id , max(salary) 最高工资 from employees where commission_pct is not null group by job_id having 最高工资>12000;
+--------+--------------+
| job_id | 最高工资     |
+--------+--------------+
| SA_MAN |     14000.00 |
+--------+--------------+
1 row in set (0.00 sec)

mysql> #3. 查询领导编号>102 的每个领导手下的最低工资>5000的领导编号是哪个,以及其 最低工资
mysql> select 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)


mysql> #4. 按员工姓名的长度分组,查询每一组的员工的个数,筛选员工个数>5的有哪些
mysql> select count(*) c,length(last_name) l from employees group by l  having c>5;
+----+------+
| c  | l    |
+----+------+
| 29 |    5 |
| 15 |    7 |
| 28 |    6 |
|  8 |    9 |
| 11 |    4 |
|  7 |    8 |
+----+------+
6 rows in set (0.06 sec)

√. 四 按多个字段分组查询

mysql> #查询每个部门每个工种的员工的平均工资
mysql> select avg(salary), department_id ,job_id from employees group by department_id,job_id;
+--------------+---------------+------------+
| avg(salary)  | department_id | job_id     |
+--------------+---------------+------------+
| 24000.000000 |            90 | AD_PRES    |
| 17000.000000 |            90 | AD_VP      |
|  5760.000000 |            60 | IT_PROG    |
| 12000.000000 |           100 | FI_MGR     |
|  7920.000000 |           100 | FI_ACCOUNT |
| 11000.000000 |            30 | PU_MAN     |
|  2780.000000 |            30 | PU_CLERK   |
|  7280.000000 |            50 | ST_MAN     |
|  2785.000000 |            50 | ST_CLERK   |
| 12200.000000 |            80 | SA_MAN     |
|  8396.551724 |            80 | SA_REP     |
|  7000.000000 |          NULL | SA_REP     |
|  3215.000000 |            50 | SH_CLERK   |
|  4400.000000 |            10 | AD_ASST    |
| 13000.000000 |            20 | MK_MAN     |
|  6000.000000 |            20 | MK_REP     |
|  6500.000000 |            40 | HR_REP     |
| 10000.000000 |            70 | PR_REP     |
| 12000.000000 |           110 | AC_MGR     |
|  8300.000000 |           110 | AC_ACCOUNT |
+--------------+---------------+------------+
20 rows in set (0.00 sec)


√. 五 添加排序

mysql>  #1. 查询每个部门每个工种的员工的平均工资>10000,并按工资的高低排序
mysql> select avg(salary), department_id ,job_id from employees group by department_id,job_id having avg(salary)>10000 order by avg(salary) desc;
+--------------+---------------+---------+
| avg(salary)  | department_id | job_id  |
+--------------+---------------+---------+
| 24000.000000 |            90 | AD_PRES |
| 17000.000000 |            90 | AD_VP   |
| 13000.000000 |            20 | MK_MAN  |
| 12200.000000 |            80 | SA_MAN  |
| 12000.000000 |           110 | AC_MGR  |
| 12000.000000 |           100 | FI_MGR  |
| 11000.000000 |            30 | PU_MAN  |
+--------------+---------------+---------+
7 rows in set (0.00 sec)


注:这是本人的学习笔记及练习,如果有错误的地方望指出一起讨论,谢谢!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容

  • 1、开启位图上下文 2、获取上下文 3、对位图上下文添加裁剪的范围,并对齐裁剪 4、从位图上下文中获取已经裁剪的图...
    后浪普拉斯阅读 3,804评论 5 2
  • 我看着屋檐滴下的雨滴,一滴连着一滴落下,落在到长满青苔的地上,不偏不倚,每一滴在碰到地面的那一刹那,都溅起小小...
    无尽亦阅读 313评论 0 1
  • 昨天提到了那位买烧烤的老板,我给了他一些建议。其中,烧烤是有形的要素,从客人那里听来的故事是无形的要素,用故事吸引...
    茶山阅读 145评论 0 1