SQL训练营任务
打卡目录
前言
阿里云天池龙珠计划,让全世界学习者公平学习优质资源,SQL训练营,12天24小时,6个任务,从MySQL基础到进阶操作
一、Task01打卡
-
编写一条 CREATE TABLE 语句,用来创建一个包含表 1-A 中所列各项的表 Addressbook (地址簿),并为 regist_no (注册编号)列设置主键约束
表1-A 表 Addressbook (地址簿)中的列
CREATE TABLE Addressbook ( regist_no INTEGER NOT NULL, name VARCHAR ( 128 ) NOT NULL, address VARCHAR ( 256 ) NOT NULL, tel_no CHAR ( 10 ), mail_address CHAR ( 20 ), PRIMARY KEY ( regist_no ) );
-
假设在创建练习1.1中的 Addressbook 表时忘记添加如下一列 postal_code (邮政编码)了,请把此列添加到 Addressbook 表中。
列名 : postal_code
数据类型 :定长字符串类型(长度为 8)
约束 :不能为 NULLALTER TABLE addressbook ADD COLUMN postal_code CHAR ( 10 ) NOT NULL;
-
编写 SQL 语句来删除 Addressbook 表。
DROP TABLE addressbook
-
编写 SQL 语句来恢复删除掉的 Addressbook 表。
被DORP TABLE命令删除的表无法进行恢复,重新执行CREATE TABLE语句
CREATE TABLE Addressbook ( regist_no INTEGER NOT NULL, name VARCHAR ( 128 ) NOT NULL, address VARCHAR ( 256 ) NOT NULL, tel_no CHAR ( 10 ), mail_address CHAR ( 20 ), PRIMARY KEY ( regist_no ) );
-
练习
删除一列 ALTER TABLE addressbook DROP COLUMN postal_code; 插入一条数据 INSERT INTO addressbook (regist_no,name,address,tel_no,mail_address) VALUES (10001,"张三","内蒙古呼和浩特","18858886888","123456@qq.com"); 插入多条数据 INSERT INTO addressbook ( regist_no, NAME, address, tel_no, mail_address ) VALUES ( 10002, "张三", "内蒙古呼和浩特", "18858886888", "123456@qq.com" ), ( 10003, "张四", "内蒙古呼和浩特", "18858886888", "123456@qq.com" ), ( 10004, "张五", "内蒙古呼和浩特", "18858886888", "123456@qq.com" ); 更新数据 UPDATE addressbook set name="王五" where regist_no = 10001 清空表 TRUNCATE TABLE addressbook
二、Task02打卡
练习题-第一部分
-
编写一条SQL语句,从product(商品)表中选取出“登记日期(regist在2009年4月28日之后”的商品,查询结果要包含product_name和regist_date两列。
SELECT product_name,regist_date from product where regist_date >= '2009-04-28'
-
请说出对product 表执行如下3条SELECT语句时的返回结果。
SELECT * FROM product WHERE purchase_price = NULL;
SELECT * FROM product WHERE purchase_price <> NULL;
SELECT * FROM product WHERE product_name > NULL;
1、空数据,什么都没有查出来
2、空数据,什么都没有查出来
3、空数据,什么都没有查出来 -
代码清单2-22(2-2节)中的SELECT语句能够从product表中取出“销售单价(saleprice)比进货单价(purchase price)高出500日元以上”的商品。请写出两条可以得到相同结果的SELECT语句。执行结果如下所示。
product_name | sale_price | purchase_price -------------+------------+------------ T恤衫 | 1000 | 500 运动T恤 | 4000 | 2800 高压锅 | 6800 | 5000
SELECT product_name, sale_price, purchase_price FROM product WHERE ( sale_price - purchase_price >= 500 ) ------------------------------------------------------------------ SELECT product_name, sale_price, purchase_price FROM product WHERE sale_price >= purchase_price + 500
-
请写出一条SELECT语句,从product表中选取出满足“销售单价打九折之后利润高于100日元的办公用品和厨房用具”条件的记录。查询结果要包括product_name列、product_type列以及销售单价打九折之后的利润(别名设定为profit)。
提示:销售单价打九折,可以通过saleprice列的值乘以0.9获得,利润可以通过该值减去purchase_price列的值获得。SELECT product_name, product_type, sale_price * 0.9 - purchase_price AS profit FROM product WHERE sale_price * 0.9 - purchase_price >= 100 AND (product_type = '办公用品' OR product_type = '厨房用具')
练习题-第二部分
-
请指出下述SELECT语句中所有的语法错误。
SELECT product_id, SUM(product_name) --本SELECT语句中存在错误。 FROM product GROUP BY product_type WHERE regist_date > '2009-09-01';
1、第一行使用了中文括号,字符串字段不能进行SUM
2、where应该在GROUP BY之前
3、product_type 未在select语句中 -
请编写一条SELECT语句,求出销售单价(sale_price列)合计值大于进货单价(purchase_price列)合计值1.5倍的商品种类。执行结果如下所示。
product_type | sum | sum -------------+------+------ 衣服 | 5000 | 3300 办公用品 | 600 | 320
SELECT product_type, sum( sale_price ), SUM( purchase_price ) FROM product GROUP BY product_type HAVING sum( sale_price ) > SUM( purchase_price )* 1.5
-
此前我们曾经使用SELECT语句选取出了product(商品)表中的全部记录。当时我们使用了ORDERBY子句来指定排列顺序,但现在已经无法记起当时如何指定的了。请根据下列执行结果,思考ORDERBY子句的内容。
select * from product order by regist_date desc,sale_price
三、Task03打卡
练习题-第一部分
-
创建出满足下述三个条件的视图(视图名称为 ViewPractice5_1)。使用 product(商品)表作为参照表,假设表中包含初始状态的 8 行数据。
条件 1:销售单价大于等于 1000 日元。 条件 2:登记日期是 2009 年 9 月 20 日。 条件 3:包含商品名称、销售单价和登记日期三列。 对该视图执行 SELECT 语句的结果如下所示。 SELECT * FROM ViewPractice5_1; 执行结果 product_name | sale_price | regist_date --------------+------------+------------ T恤衫 | 1000 | 2009-09-20 菜刀 | 3000 | 2009-09-20
CREATE VIEW ViewPractice5_1 AS SELECT product_name, sale_price, regist_date FROM product WHERE sale_price >= 1000 AND regist_date = '2009-09-20'
-
向习题一中创建的视图 ViewPractice5_1 中插入如下数据,会得到什么样的结果呢?
INSERT INTO ViewPractice5_1 VALUES (' 刀子 ', 300, '2009-11-02');
插入报错,向视图中插入数据时同时也会操作原表,原表中有不为空的字段所以会报错
-
请根据如下结果编写 SELECT 语句,其中 sale_price_all 列为全部商品的平均销售单价。
product_id | product_name | product_type | sale_price | sale_price_all ------------+-------------+--------------+------------+--------------------- 0001 | T恤衫 | 衣服 | 1000 | 2097.5000000000000000 0002 | 打孔器 | 办公用品 | 500 | 2097.5000000000000000 0003 | 运动T恤 | 衣服 | 4000 | 2097.5000000000000000 0004 | 菜刀 | 厨房用具 | 3000 | 2097.5000000000000000 0005 | 高压锅 | 厨房用具 | 6800 | 2097.5000000000000000 0006 | 叉子 | 厨房用具 | 500 | 2097.5000000000000000 0007 | 擦菜板 | 厨房用具 | 880 | 2097.5000000000000000 0008 | 圆珠笔 | 办公用品 | 100 | 2097.5000000000000000
知识要点:Sql执行顺序 书写顺序: SELECT》FROM 》WHERE》GROUP BY》HAVE》ORDER BY 执行顺序: FROM 》WHERE》GROUP BY》HAVE》SELECT》ORDER BY 1、关联子查询的执行逻辑完全不同于正常的SELECT语句。 2、关联子查询执行逻辑如下: (1)先从主查询的Product表中product _type列取出第一个值,进入子查询中,得到子查询结果,然后返回父查询,判断父查询的where子句条件,则返回整个语句的第1条结果。 (2)重复上述操作,直到所有主查询中的Product表中product _type列记录取完为止。得出整个语句的结果集,就是最后的答案。
SELECT product_id, product_name, product_type, sale_price, ( SELECT AVG( sale_price ) FROM product ) AS sale_price_all FROM product
-
请根据习题一中的条件编写一条 SQL 语句,创建一幅包含如下数据的视图(名称为AvgPriceByType)。
product_id | product_name | product_type | sale_price | avg_sale_price ------------+-------------+--------------+------------+--------------------- 0001 | T恤衫 | 衣服 | 1000 |2500.0000000000000000 0002 | 打孔器 | 办公用品 | 500 | 300.0000000000000000 0003 | 运动T恤 | 衣服 | 4000 |2500.0000000000000000 0004 | 菜刀 | 厨房用具 | 3000 |2795.0000000000000000 0005 | 高压锅 | 厨房用具 | 6800 |2795.0000000000000000 0006 | 叉子 | 厨房用具 | 500 |2795.0000000000000000 0007 | 擦菜板 | 厨房用具 | 880 |2795.0000000000000000 0008 | 圆珠笔 | 办公用品 | 100 | 300.0000000000000000
提示:其中的关键是 avg_sale_price 列。与习题三不同,这里需要计算出的 是各商品种类的平均销售单价。这与使用关联子查询所得到的结果相同。 也就是说,该列可以使用关联子查询进行创建。问题就是应该在什么地方使用这个关联子查询。
CREATE VIEW AvgPriceByType AS SELECT product_id, product_name, product_type, sale_price, ( SELECT AVG( sale_price ) FROM product AS p2 WHERE p1.product_type = p2.product_type GROUP BY product_type ) AS avg_sale_price FROM product AS p1
练习题-第二部分 ```
-
运算或者函数中含有 NULL 时,结果全都会变为NULL ?(判断题)
√
-
对本章中使用的 product(商品)表执行如下 2 条 SELECT 语句,能够得到什么样的结果呢?
SELECT product_name, purchase_price FROM product WHERE purchase_price NOT IN (500, 2800, 5000);
SELECT product_name, purchase_price FROM product WHERE purchase_price NOT IN (500, 2800, 5000, NULL);
第一条语句查询出了purchase_price为500,2800,5000的数据集,其中不包含为NULL的数据
第二条语句查询结果为空,因为IN 和 NOTIN是无法取出NULL的数据
备注:在使用IN 和 NOT IN 时是无法选取出NULL数据的。 -
按照销售单价( sale_price)对练习 6.1 中的 product(商品)表中的商品进行如下分类。
低档商品:销售单价在1000日元以下(T恤衫、办公用品、叉子、擦菜板、 圆珠笔)
中档商品:销售单价在1001日元以上3000日元以下(菜刀)
高档商品:销售单价在3001日元以上(运动T恤、高压锅)
请编写出统计上述商品种类中所包含的商品数量的 SELECT 语句,结果如下所示。执行结果:
low_price | mid_price | high_price ----------+-----------+------------ 5 | 1 | 2
SELECT SUM( CASE WHEN sale_price <= 1000 THEN 1 ELSE 0 END ) AS low_price, SUM( CASE WHEN sale_price BETWEEN 1001 AND 3000 THEN 1 ELSE 0 END ) AS mid_price, SUM( CASE WHEN sale_price >= 3001 THEN 1 ELSE 0 END ) AS high_price FROM product;
总结
一、算术函数
ABS –绝对值
语法:ABS( 数值 )
ABS 函数用于计算一个数字的绝对值,表示一个数到原点的距离。
当 ABS 函数的参数为NULL时,返回值也是NULL。
SELECT m,ABS(m) AS abs_col FROM samplemath;
结果:
m | abs_col |
---|---|
500.00 | 500.00 |
-500.00 | 500.00 |
-1850.00 | 1850.00 |
NULL | NULL |
MOD – 求余数
语法:MOD( 被除数,除数 )
MOD 是计算除法余数(求余)的函数,是 modulo 的缩写。小数没有余数的概念,只能对整数列求余数。
注意:主流的 DBMS 都支持 MOD 函数,只有SQL Server 不支持该函数,其使用%符号来计算余数。
SELECT n,p,MOD ( n, p ) AS mod_col FROM samplemath;
结果:
n | p | mod_col |
---|---|---|
5 | 2 | 1 |
NULL | NULL | NULL |
0 | NULL | NULL |
1 | NULL | NULL |
NULL | 2 | NULL |
ROUND – 四舍五入
语法:ROUND( 对象数值,保留小数的位数 )
ROUND 函数用来进行四舍五入操作。
注意:当参数 保留小数的位数 为变量时,可能会遇到错误,请谨慎使用变量。
SELECT m,ROUND( m, 1 ) AS round_colS FROM samplemath;
结果:
m | round_colS |
---|---|
500.00 | 500.0 |
-180.00 | -180.0 |
2.270 | 2.3 |
8.110 | 8.1 |
二、字符串函数
CONCAT – 拼接
语法:CONCAT(str1, str2, str3)
MySQL中使用 CONCAT 函数进行拼接。
SELECT str1,str2,str3,CONCAT( str1, str2, str3 ) AS str_concat FROM samplestr
结果:
str1 | str2 | str3 | str_concat |
---|---|---|---|
opx | rt | NULL | NULL |
太阳 | 月亮 | 火星 | 太阳月亮火星 |
LENGTH – 字符串长度
语法:LENGTH( 字符串 )
SELECT str1,LENGTH( str1 ) AS len_str FROM samplestr
结果:
str1 | len_str |
---|---|
opx | 3 |
太阳 | 6 |
@!#$% | 5 |
abc哈哈 | 9 |
NULL | NULL |
LOWER – 小写转换
LOWER 函数只能针对英文字母使用,它会将参数中的字符串全都转换为小写。该函数不适用于英文字母以外的场合,不影响原本就是小写的字符。
类似的, UPPER 函数用于大写转换。
SELECT str1,LOWER( str1 ) AS low_str FROM samplestr
结果:
str1 | low_str |
---|---|
opx | opx |
太阳 | 太阳 |
@!#$% | @!#$% |
ABC | abc |
NULL | NULL |
REPLACE – 字符串的替换
语法:REPLACE( 对象字符串,替换前的字符串,替换后的字符串 )
REPLACE( field,search,replace )
语义:将列名:field 中出现的search字符串,全部替换成replace字符串。
SELECT str1,REPLACE ( str1, "a", "啊" ) AS rep_str FROM samplestr
结果:
str1 | rep_str |
---|---|
opx | opx |
abc | 啊bc |
aaa | 啊啊啊 |
SUBSTRING/SUBSTR – 字符串的截取
语法:SUBSTRING (对象字符串 FROM 截取的起始位置 FOR 截取的字符数)
使用 SUBSTRING 函数 可以截取出字符串中的一部分字符串。截取的起始位置从字符串最左侧开始计算,索引值起始为1。
SELECT str1,SUBSTRING( str1 FROM 3 FOR 2 ) AS sub_str FROM samplestr
结果:
str1 | rep_str |
---|---|
opx | x |
abc | 啊c |
aaaa | aa |
(扩展内容)SUBSTRING_INDEX – 字符串按索引截取
语法:SUBSTRING_INDEX (原始字符串, 分隔符,n)
该函数用来获取原始字符串按照分隔符分割后,第 n 个分隔符之前(或之后)的子字符串,支持正向和反向索引,索引起始值分别为 1 和 -1。
SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
www.mysql
SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
mysql.com
获取第1个元素比较容易,获取第2个元素/第n个元素可以采用二次拆分的写法。
SELECT SUBSTRING_INDEX('www.mysql.com', '.', 1);
www
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('www.mysql.com', '.', 2), '.', -1);
mysql
三、日期函数
CURRENT_DATE – 获取当前日期
SELECT CURRENT_DATE;
[2020-08-08]
CURRENT_TIME – 当前时间
SELECT CURRENT_TIME;
[17:26:09]
CURRENT_TIMESTAMP – 当前日期和时间
SELECT CURRENT_TIMESTAMP;
[2020-08-08 17:27:07]
EXTRACT – 截取日期元素
语法:EXTRACT(日期元素 FROM 日期)
使用 EXTRACT 函数可以截取出日期数据中的一部分,例如“年”
“月”,或者“小时”“秒”等。该函数的返回值并不是日期类型而是数值类型
SELECT CURRENT_TIMESTAMP as now,
EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS year,
EXTRACT(MONTH FROM CURRENT_TIMESTAMP) AS month,
EXTRACT(DAY FROM CURRENT_TIMESTAMP) AS day,
EXTRACT(HOUR FROM CURRENT_TIMESTAMP) AS hour,
EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) AS Minute,
EXTRACT(SECOND FROM CURRENT_TIMESTAMP) AS second;
结果:
now | year | month | day | hour | Minute | second |
---|---|---|---|---|---|---|
2022-06-07 11:01:35 | 2022 | 6 | 7 | 11 | 1 | 35 |
四、转换函数
“转换”这个词的含义非常广泛,在 SQL 中主要有两层意思:一是数据类型的转换,简称为类型转换,在英语中称为cast;另一层意思是值的转换。
CAST – 类型转换
语法:CAST(转换前的值 AS 想要转换的数据类型)
SELECT CAST('0001' AS SIGNED INTEGER) AS int_col;
[1]
COALESCE – 将NULL转换为其他值
语法:COALESCE(数据1,数据2,数据3……)
COALESCE 是 SQL 特有的函数。该函数会返回可变参数 A 中左侧开始第 1个不是NULL的值。参数个数是可变的,因此可以根据需要无限增加。
在 SQL 语句中将 NULL 转换为其他值时就会用到转换函数。
SELECT COALESCE
( NULL, 11 ) AS col_1,
COALESCE ( NULL, 'hello world', NULL ) AS col_2,
COALESCE ( NULL, NULL, '2020-11-01' ) AS col_3;
结果:
col_1 | col_2 | col_3 |
---|---|---|
11 | hello world | 2020-11-01 |
五、LIKE谓词 – 用于字符串的部分一致查询
SELECT * FROM samplelike WHERE strcol LIKE 'ddd%';
其中的%是代表“零个或多个任意字符串”的特殊符号,本例中代表“以ddd开头的所有字符串”。
SELECT * FROM samplelike WHERE strcol LIKE 'abc__';
_下划线匹配任意 1 个字符
使用 _(下划线)来代替 %,与 % 不同的是,它代表了“任意 1 个字符”。
六、BETWEEN谓词 – 用于范围查询
使用 BETWEEN 可以进行范围查询。该谓词与其他谓词或者函数的不同之处在于它使用了 3 个参数。
SELECT product_name, sale_price FROM product WHERE sale_price BETWEEN 100 AND 1000;
BETWEEN 的特点就是结果中会包含 100 和 1000 这两个临界值,也就是闭区间。如果不想让结果中包含临界值,那就必须使用 < 和 >。
七、IS NULL、 IS NOT NULL – 用于判断是否为NULL
为了选取出某些值为 NULL 的列的数据,不能使用 =,而只能使用特定的谓词IS NULL。
SELECT product_name, purchase_price FROM product WHERE purchase_price IS NULL;
与此相反,想要选取 NULL 以外的数据时,需要使用IS NOT NULL。
SELECT product_name, purchase_price FROM product WHERE purchase_price IS NOT NULL;
八、IN谓词 – OR的简便用法
SELECT product_name, purchase_price FROM product WHERE purchase_price = 320 OR purchase_price = 500 OR purchase_price = 5000;
SELECT product_name, purchase_price FROM product WHERE purchase_price IN (320, 500, 5000);
SELECT product_name, purchase_price FROM product WHERE purchase_price NOT IN (320, 500, 5000);
在使用IN 和 NOT IN 时是无法选取出NULL数据的。
九、EXIST 谓词
EXIST谓词的使用方法
谓词的作用就是 “判断是否存在满足某种条件的记录”。
如果存在这样的记录就返回真(TRUE),如果不存在就返回假(FALSE)。
EXIST(存在)谓词的主语是“记录”。
十、CASE 表达式
CASE WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
.
.
.
ELSE <表达式>
END
十一、并集
MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。
UNION 等集合运算符通常都会除去重复的记录
SELECT product_id, product_name FROM product
UNION
SELECT product_id, product_name FROM product2;
包含重复行的集合运算 UNION ALL
SELECT product_id, product_name FROM product
UNION ALL
SELECT product_id, product_name FROM product2;
十二、连接
-INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录
-LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录
-RIGHT JOIN(右连接):与LEFT JOIN相反,用于获取右表所有记录,即使左表没有对应匹配的记录。
窗口函数
函数 (字段名) OVER ( 子句 )
函数 (统计字段名) OVER ( PARTITION BY 分组字段名 ORDER BY 排序字段名 ROWS BETWEEN ...AND ...)
-- over关键字用于指定函数的窗口范围,
-- partition by 用于对表分组,
-- order by子句用于对分组后的结果进行排序。
-- ROWS BETWEEN ...AND ...:指定行数统计的的范围;如果其前面有PARTITION BY 字段,将在分好的组的组内指定输出行数,即在分组后的窗口再划分为一个个小窗口,用作滑动窗口在通常有以下几种情况
应用场景:
- 排名问题,例如:查利润的月排名;
- TOPN问题,例如:查每种商品利润最高的两个月
注意:窗口函数是对where或者group by子句处理后的结果再进行二次操作,因此会按照SQL语句的运行顺序,窗口函数一般放在select子句中(from前)
RANK():并列排序,跳过重复序号 - 1,2,2,4
SELECT
product_name,
product_type,
sale_price,
RANK() OVER (PARTITION BY product_type ORDER BY sale_price ) AS ranking
FROM
product
根据product_type分组,加sale_price进行排序
DENSE_RANK():并列排序,不跳过重复序号 -1,2,2,3,4,5
SELECT
product_name,
product_type,
sale_price,
DENSE_RANK() OVER ( ORDER BY sale_price ) AS ranking
FROM
product
ROW_NUMBER():顺序排序 -1,2,3,4,5
SELECT
product_name,
product_type,
sale_price,
ROW_NUMBER() OVER ( ORDER BY sale_price ) AS ranking
FROM
product
聚合函数在窗口函数上的使用
sum()、count()、avg()、max()、min()
聚合类窗口函数与普通聚合函数区别:
- 普通聚合函数将多个记录合为一条(多对一)
- 窗口聚合函数每一条记录执行得到一个结果,有几条记录执行完后还是几条(多对多)
SELECT
product_id,
product_name,
sale_price,
COUNT( 1 ) OVER ( ORDER BY product_id ) AS count,
SUM( sale_price ) OVER ( ORDER BY product_id ) AS current_sum,
AVG( sale_price ) OVER ( ORDER BY product_id ) AS current_avg,
max( sale_price ) OVER ( ORDER BY product_id ) AS max,
min( sale_price ) OVER ( ORDER BY product_id ) AS min
FROM
product;
文字表述不清楚,看结果比较好理解
计算移动平均
SELECT
product_id,
product_name,
sale_price,
AVG( sale_price ) OVER ( ORDER BY product_id ROWS 2 PRECEDING ) AS moving_avg,
AVG( sale_price ) OVER ( ORDER BY product_id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) AS moving_avg
FROM
product
PRECEDING(“之前”), 将框架指定为 “截止到之前 n 行”,加上自身行
FOLLOWING(“之后”), 将框架指定为 “截止到之后 n 行”,加上自身行
BETWEEN 1 PRECEDING AND 1 FOLLOWING,将框架指定为 “之前1行” + “之后1行” + “自身”
解析
AVG( sale_price ) OVER ( ORDER BY product_id ROWS 2 PRECEDING ) AS moving_avg,
获取之前俩行加上自身行的平均数
解析
AVG( sale_price ) OVER ( ORDER BY product_id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
获取前一行+当前行+下一行的平均数
GROUPING运算符
ROLLUP - 计算合计及小计
SELECT product_type
,regist_date
,SUM(sale_price) AS sum_price
FROM product
GROUP BY product_type, regist_date WITH ROLLUP
使用 WITH ROLLUP,此函数是对聚合函数进行求和,注意 with rollup是对 group by 后的第一个字段,进行分组求和。