一、完整建表 SQL(MySQL 语法):
CREATE TABLE Activities ( sell_date DATE, product VARCHAR(30) ); 该表没有主键(具有唯一值的列)。它可能包含重复项。 此表的每一行都包含产品名称和在市场上销售的日期。INSERT INTO Activities(sell_date, product) VALUES ('2020-05-30','Headphone'), ('2020-06-01','Pencil'), ('2020-06-02','Mask'), ('2020-05-30','Basketball'), ('2020-06-01','Bible'), ('2020-06-02','Mask'), ('2020-05-30','T-Shirt');二、需求:
编写解决方案找出每个日期、销售的不同产品的数量及其名称。
每个日期的销售产品名称应按词典序排列。
返回按sell_date排序的结果表。
结果表结果格式如下例所示。
三、 思路与解题:
题目要求拆解
- 按照
sell_date分组; num_sold:当天去重之后产品的个数;products:当天去重后的产品,字典升序排列,用逗号拼接;- 最终结果按
sell_date升序排序。
两个关键:
GROUP_CONCAT(字段 ORDER BY 字段 ASC SEPARATOR ',')分组之后,把多行的字符串拼接成一行,ORDER BY可以指定拼接时的字典顺序;COUNT(DISTINCT product):分组前必须先去重:同一天同一个产品重复出现只算 1 次。
完整 AC 代码
SELECT sell_date, COUNT(DISTINCT product) num_sold, GROUP_CONCAT(DISTINCT product ORDER BY product SEPARATOR ',') products FROM Activities GROUP BY sell_date ORDER BY sell_date;分步演示,拿示例数据推演
原始数据:
| sell_date | product |
|---|---|
| 2020-05-30 | Headphone |
| 2020-06-01 | Pencil |
| 2020-06-02 | Mask |
| 2020-05-30 | Basketball |
| 2020-06-01 | Bible |
| 2020-06-02 | Mask |
| 2020-05-30 | T-Shirt |
针对
2020‑05‑30:去重之后产品:
Basketball, Headphone, T‑Shirt
COUNT(DISTINCT product)→ 3;GROUP_CONCAT拼接得到Basketball,Headphone,T‑Shirt。2020‑06‑02:
去重之后只有
Mask,数量为 1。
四、总结
group_concat(distinct 列 order by 列 asc separator '分隔符')
- 不加
DISTINCT:重复值都会拼接进去; ORDER BY可以控制拼接时的排序顺序,完美契合本题字典序;SEPARATOR '符号':默认分隔符是逗号,也可以改成空格或者别的字符
五、拓展(面试知识点)
- MySQL 默认
GROUP_CONCAT拼接字符串长度有限制(默认 1024 字符),超长会被截断;真实业务里超长场景需要修改系统参数; - 8.0 版本没有别的替代方案,分组拼接字符串
GROUP_CONCAT是 MySQL 专属核心函数