mysql 分组排序,多组里面取topN.

下面是原表.
需要实现:按照年级分组,取出每个年级年龄最大同学(取前两个年龄最大)的信息。需要的效果如图二所示。
在这里插入图片描述
效果:
在这里插入图片描述

我们需要了解两个个小知识点,组合使用就可以了。

1.分组合并函数,group_concat()
group_concat 默认的分隔符是 ‘,’.
按照年级分组, 年级只有两个,所以会分成两组,只显示两行。 该函数地作用在于,可以把组内所有字段值,可选择地显示出来
在这里插入图片描述

2.mysql打散一个字符串成一列的方法.
按照 ‘,’ 进行分割,并打散成一列数据.
在这里插入图片描述
思路:
通过年级分组后,对每个年级里面所有的年龄进行排序,.
再通过截取前两个名的id.
再把两个年级的所有的id合并在一起.成一个长字符串.
这个字符串,再通过上面的打散,打成一列. 作为一张结果表和原表关联.
取值即可.

合并使用如下:
在这里插入图片描述
sql如下:


set @qqq='sss' ;  -- 定义sesion变量获取 id 集合
select group_concat(a.ids) into @qqq from (   -- id集合存入变量
select
	SUBSTRING_INDEX(group_concat(id order by age desc),',',2) ids,  -- 分组合并函数,再按照','分割获取前两名
	'1' as xx
from t1 GROUP BY grade
) a GROUP BY a.xx ;

-- 打散这个字符串 '4,6,5,7'
select t1.* from (
SELECT 
    SUBSTRING_INDEX(SUBSTRING_INDEX(@qqq,',',help_topic_id+1),',',-1) AS num 
FROM 
    mysql.help_topic 
WHERE 
    help_topic_id < LENGTH(@qqq)-LENGTH(REPLACE(@qqq,',',''))+1 
		) b 
INNER join t1 on t1.id = b.num ORDER  BY t1.grade

.
案例表的结构和数据:

DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1`  (
  `id` int(11) NOT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(5) NULL DEFAULT NULL,
  `grade` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

INSERT INTO `t1` VALUES (1, '小明', 18, '一年级');
INSERT INTO `t1` VALUES (3, '小熊', 19, '六年级');
INSERT INTO `t1` VALUES (2, '阿宝', 20, '一年级');
INSERT INTO `t1` VALUES (4, '小白', 21, '一年级');
INSERT INTO `t1` VALUES (5, '大黄', 22, '六年级');
INSERT INTO `t1` VALUES (6, '小K', 23, '一年级');
INSERT INTO `t1` VALUES (7, '小仓', 24, '六年级');
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值