数据库专辑--SQL分类汇总(group by...with rollup),增加“总计”字段
创始人
2024-03-25 01:19:15
0

系列文章

C#底层库–数据库访问帮助类(MySQL版)

数据库专辑–WITH CHECK OPTION的用法

文章目录

  • 系列文章
  • 前言
  • 一、概念介绍
  • 二、测试用例
    • 2.1 创建表
    • 2.2 初始化数据
    • 2.3 数据查询
    • 2.4 分析问题
    • 2.5 解决问题
    • 2.6 推荐另一种写法,使用COALESCE
  • 三、用法总结


前言

本专辑主要介绍SQL的功能与特点、SQL数据定义语言(表、视图、索引、约束)、SQL数据操作语言(数据检索、数据插入、数据删除、数据更新)、创建与删除触发器、SQL数据控制语言(安全性和授权、事务处理)以及嵌入式SQL。
如果你对本专辑感兴趣,持续关注吧。大家有任何问题,也可以评论区反馈,私信我。

一、概念介绍

数据库select查询语句格式:

SELECT [ALL|DISTINCT]<目标列表达式>[,<目标列表达式>]…
FROM <表名或视图名>[,<表名或视图名>]
[WHERE <条件表达式>]
[GROUP BY <列名 1> [HAVING<条件表达式>] ]
[ORDER BY <列名 2> [ASC|DESC]…]

group by作用:

主要用来对查询的结果进行分组,相同组合的分组条件在结果集中只显示一行记录。使用group by从句时,通过添加聚合函数(主要有COUNT()、SUM、MAX()、MIN()等)可以使数据聚合。

with rollup:

rollup 是根据维度在数据结果集中进行的聚合操作。

OALESCE作用:

OALESCE是一个函数, (expression_1, expression_2, …,expression_n)依次参考各参数表达式,遇到非null值即停止并返回该值。如果所有的表达式都是空值,最终将返回一个空值。使用COALESCE在于大部分包含空值的表达式最终将返回空值。

二、测试用例

2.1 创建表

创建学生信息表student

CREATE TABLE student(
sid VARCHAR(10) PRIMARY KEY NOT NULL COMMENT '学生学号',
class VARCHAR(10) NOT NULL COMMENT '班级',
profession VARCHAR(10) NOT NULL COMMENT '专业',
NAME VARCHAR(20) NOT NULL COMMENT '学生姓名',
phone VARCHAR(15) NULL COMMENT '手机',
sex TINYINT(1) NULL COMMENT '性别',
cityid VARCHAR(20) NULL COMMENT '城市编号'
)

创建城市表city

CREATE TABLE city(
cityid VARCHAR(32) PRIMARY KEY NOT NULL COMMENT '城市编号',
cityname VARCHAR(32) NOT NULL COMMENT '城市名称'
)

2.2 初始化数据

插入的学生数据

-- 插入的学生数据
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513001','3','jsj','张超','18652820000',1,'zj');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513002','4','jsj','王凯','18652820001',0,'zj');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513003','5','jsj','艾军','18652820002',0,'zj');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513004','3','jsj','赵晨欣','18652820003',0,'nt');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513005','3','chinese','陈苏娜','18652820004',0,'xz');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513006','3','chinese','李艳','18652820005',0,'zj');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513007','3','math','葛帅','18652820006',0,'yz');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513008','3','english','王梦雅','18652820007',1,'yc');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513009','3','jsj','张婷婷','18652820008',1,'xz');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513010','4','jsj','杨燕','18652820009',1,'zj');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513011','4','jsj','张灵敏','18652820010',0,'jy');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513012','5','jsj','王婷','18652820011',1,'yz');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513013','5','english','王爱岚','18652820012',1,'zj');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513014','5','english','张雪婷','18652820013',1,'nt');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513015','5','chinese','朴月亮','18652820014',0,'nj');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513016','5','chinese','陈思佳','18652820015',0,'ha');
INSERT INTO student(sid, class, profession,NAME,phone,sex,cityid) VALUES('140513017','5','english','刘欣','18652820016',0,'yc');

运行结果:
在这里插入图片描述

插入城市数据

-- 插入的数据
INSERT INTO city(cityid,cityname) VALUES('nj','南京');
INSERT INTO city(cityid,cityname) VALUES('yc','盐城');
INSERT INTO city(cityid,cityname) VALUES('nt','南通');
INSERT INTO city(cityid,cityname) VALUES('xz','徐州');
INSERT INTO city(cityid,cityname) VALUES('zj','镇江');
INSERT INTO city(cityid,cityname) VALUES('yz','扬州');
INSERT INTO city(cityid,cityname) VALUES('ha','淮安');

运行结果:
在这里插入图片描述

2.3 数据查询

查询学生在各个城市人数分布情况,并在最后一行数据显示人数总计。

--查询人数分布情况
SELECT ci.cityname AS '城市',
COUNT(st.name) AS '人数'
FROM student AS st
JOIN city AS ci ON st.cityid=ci.cityid
GROUP BY ci.cityname WITH ROLLUP;

运行结果:
在这里插入图片描述
发现问题:我们在使用group by...with rollup语句时,最后一行的字段显示为null,显得特别别扭,如上图所示。

2.4 分析问题

我们在使用group by…with rollup时,最后一行的字段显示为null,并不是“总计”字段,显得和别扭也给界面绑定数据源带来的麻烦。
现在要求将null字段列显示为“总计”,查阅了资料也没找到相应的解决方案,不过就在我一筹莫展之际有一条博客引起我的注意,其内容如下:
在这里插入图片描述

2.5 解决问题

使用grouping这个函数发现一直报错提示无法识别,仔细观察一下原来这是sql的语法,难道MySQL就实现不了了吗?后又查询了一些资料,发现网上很多人关于group by会总结果都是使用sum计算的。没办法只得自己想办法了,我首先想到的方法是使用带条件的子查询,输出到最后一条数据时显示“总计”字段,但又嫌太复杂没有写。后来按上文研究了一下case语句,觉得这个视乎可行,也行可以使用case判断为null是替换数据,于是写出了如下的代码:
查询语句:

SELECT CASE
WHEN ci.cityname IS NULL THEN '总计'
ELSE ci.cityname
END AS '城市',
COUNT(st.name) AS '人数'
FROM student AS st
JOIN city AS ci ON st.cityid=ci.cityid
GROUP BY ci.cityname WITH ROLLUP;

或者这样

SELECT CASE
WHEN ci.cityname IS NULL THEN '总计'
ELSE ci.cityname
END AS '城市',
COUNT(ci.cityname) AS '人数'
FROM student AS st
JOIN city AS ci ON st.`cityid`=ci.`cityid`
GROUP BY ci.cityname WITH ROLLUP;

运行结果:
在这里插入图片描述

2.6 推荐另一种写法,使用COALESCE

本方法是由网友【愤怒的塔塔】推荐,使用COALESCE函数。
查询语句

SELECT
COALESCE(ci.cityname, '总计') AS '城市',
COUNT(ci.cityname) AS '人数'
FROM student AS st
JOIN city AS ci ON st.cityid=ci.cityid
GROUP BY ci.cityname WITH ROLLUP

运行结果:
在这里插入图片描述

三、用法总结

本文章于2018年6月发表过,由于一些原因无法显示,原文链接https://blog.csdn.net/youcheng_ge/article/details/77728290。
原MySQL数据库版本比较旧,使用grouping,判断NULL值(is null、not null)有异常问题,无法筛选数据,现在的数据库版本已修复该问题,不存在了。
如果您在使用2.4节的SQL语句,无法正确显示结果,可以使用 <=>或者IFNULL()函数,语句如下。
查询语句

--查询语句1
SELECT CASE
WHEN ci.cityname <=> NULL THEN '总计'
ELSE ci.cityname
END AS '城市',
COUNT(ci.cityname) AS '人数'
FROM student AS st
JOIN city AS ci ON st.cityid=ci.cityid
GROUP BY ci.cityname WITH ROLLUP
--查询语句2
SELECT IFNULL(ci.cityname,'合计') AS '城市',
COUNT(ci.cityname) AS '人数'
FROM student AS st
JOIN city AS ci ON st.cityid=ci.cityid
GROUP BY ci.cityname WITH ROLLUP

运行结果均是:
在这里插入图片描述
综上所述,我个人而言推荐使用SQL中自带的总计函数 COALESCE(a,b),毕竟使用自带的函数不容易出错。

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...