您的位置:首页 > 数据库 > MySQL

mysql获取所有分类的前n条记录的两种方法浅析

2017-01-11 17:29 274 查看
当日看点 2016-12-31 17:21

项目中有个需求是获取出展会分类下的前n条展商。

刚开始的思路是用group by 获取出展会的分类,后面再根据分类获取该分类下的n个展商,但也需要第一次获取出展会的时候也获取所有的每个展会分类下的n条展商。

CSDN上的有一个类似的问题:mysql中有个表:article(字段:id,type,date),type有1-10,10种类型。现在要用SQL找出每种类型中时间最新的前N个数据组成的集合。

select a1.* from article a1

inner join

(select a.type,a.date from article a left join article b

on a.type=b.type and a.date<=b.date

group by a.type,a.date

having count(b.date)<=N

)b1

on a1.type=b1.type and a1.date=b1.date

order by a1.type,a1.date desc

用一条SQL语句实现了

由于不是很理解这条语句的运行机制,拆分语句去测了一下

根据上面这条语句新建了一个test1数据表 有123 3种分类,对应有时间





表left join 自身获取数据符合预期

Left join 的条件改为 on a.type=b.type and a.date<=b.date,比上一次多了一个条件 a.date<=b.date



加入a.date<=b.date之后left join 出来的结果少了一些



我对left join on 的理解:每一条符合条件的b表记录都会附加在a表对应记录后(类似加字段),有多个符合条件的b表记录对应a表记录时,这是一对多的关系,a表记录会复制一个记录再往后面添加b记录字段,最后合成一张新的a表。

然后left join 整体流程是 数据库先取得 a表全部数据,再根据 a.type=b.type and a.date<=b.date取得 b表相关数据 然后拼接组装出 a.*,b.*的合成数据并返回

再对结果集group by a.type,a.date



同理把group by a.type,a.date 改为 group by b.type,b.date 也可按照这种思路对 btype, bdate 分组

后面的having count(b.date)<=N 就好理解了,对分组后的数据过滤,取得符合条件的数据,就是最新的前n条数据。这里的b.date改成a.date结果是一样的。

最后用这种方法实现了效果

select a.* from exhibitor a left join exhibitor b

on a.exhibitionid = b.exhibitionid and a.exhibitorid <= b.exhibitorid

group by a.exhibitionid ,a.exhibitorid

having count(b.exhibitorid) <=5

但是数据量大的时候效果不理想。

最后用这种办法实现取得前n条数据

string sql = @"SELECT * FROM (SELECT *, @num := if(@exhibitionid = exhibitionid, @num := @num + 1, 1) as row_num,@exhibitionid := exhibitionid FROM exhibitor order by exhibitionid) as temp WHERE row_num <=5";

展商按展会id排列,把exhibitionid 赋值给@exhibitionid ,@num根据@exhibitionid 是否等于当前exhibitionid,等于num+1,不等于说明遇到了新的分类,num重新等于1,最后得到每个展会下面的展商按照row_num从1开始排列。筛选出row_num <=N,即可选出前n条记录。

附:

1、

mysql 中“:=” 是真正意义上的赋值操作,左边的变量设置为右边的值。

"=" 则只在两种情况下作为赋值用,第一种就是在SET语句里面,SET var = value;

另一种是在UPDATE语句里面的那个SET,如update table_name set column_name where....。

除了方面这两种情况外"="则作为比较操作符使用。

2、

select * from tablea a inner join tableb b on a.id=b.aid 就相当于 select * from tablea a,tableb b where a.id=b.aid 没什么区别,写法不一样,后者更利于扩展和移植,因为有的数据库是不支持inner join的

3、

查询hm有重复的记录

select hm,count(*) from a group by hm having count(*)>1

查询hm和xm都有重复

select hm,xm count(*) from a group by hm,xm having count(*)>1

嗯,写完了,果然写乱了,算是我的第一篇文章,就当做我的个人笔记吧,还请多多包涵。2016的最后一天,好冷。加油!

本文为头条号作者发布,不代表今日头条立场。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: