关于分组查询的一道常见sql题
背景:一道常见的sql的分组计算题,题目如下:
按照角色分组算出每个角色按有办公室和没办公室的统计人数(列出角色,数量,有无办公室,注意一个角色如果部分有办公室,部分没有需分开统计)
如下,构造测试环境与对应的测试数据来验证
1.打开虚拟机,确认开启mysql服务

2.打开navicat,连接数据库,testdb库

3.创建表,主键设定为姓名
create table Employee (
Role VARCHAR(64) DEFAULT NULL,
Name VARCHAR(64) PRIMARY KEY,
Building VARCHAR(64) DEFAULT NULL,
Years_employed VARCHAR(64) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

4.插入测试数据:(手动或inset)
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Engineer', 'Becky A.', '1e', '4');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Engineer', 'Dan B.', '1e', '2');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Engineer', 'Sharon F.', '1e', '6');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Engineer', 'Dan M.', '1e', '4');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Engineer', 'Malcom S.', '1e', '1\r\n');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Artist', 'Tylar S.', '2w', '2');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Artist', 'Sherman D.', '2w', '8');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Artist', 'Jakob J.', '2w', '6');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Artist', 'Lillia A.', '2w', '7');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Artist', 'Brandon J.', '2w', '7');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Manager', 'Scott K.', '1e', '9');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Manager', 'Shirlee M.', '1e', '3');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Manager', 'Manager', '2w', '6');
INSERT INTO `testdb`.`Employee` (`Role`, `Name`, `Building`, `Years_employed`) VALUES ('Engineer', 'Yancy I.', 'nu

5.求解sql,分别根据不同的条件使用where过滤,然后group by再count计算,最后用union all进行连接
sql语句如下:
select Role,count(*) as number,"Y"as haveBuilding from Employees where Building <> 'NULL' GROUP BY Role
union all
select Role,count(*) as number,"N" as haveBuilding from Employees where Building = 'NULL' GROUP BY Role
查看运行结果:

6.另一种解决,使用case when语句是否满足的条件并且group by时添加此条件:
sql语句如下:
select Role,count(name),
case when Building <> 'NUll' Then "Y" else "N" end as haveBuilding
from Employees
GROUP BY Role,haveBuilding
查询运行结果:

7.扩展,使用GROUP_CONCAT函数可以在分组的同时连接所需查看的固定字段的值。
sql语句如下:
select Role,count(name),
case when Building <> 'NUll' Then "Y" else "N" end as haveBuilding,GROUP_CONCAT(Building)
from Employees
GROUP BY Role,haveBuilding
查看运行结果:

8,扩展,使用GROUP_CONCAT结合DISTINCT语句可以将连接后内重复的值过滤
sql语句如下:
select Role,count(name),
case when Building <> 'NUll' Then "Y" else "N" end as haveBuilding,GROUP_CONCAT(DISTINCT Building) as BuildingInfo
from Employees
GROUP BY Role,haveBuilding
查看运行结果:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了