mysql获取所有分类的前n条记录的两种方法浅析
项目中有个需求是获取出展会分类下的前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的最后一天,好冷。加油!
mysql获取所有分类的前n条记录的两种方法浅析的更多相关文章
- 【转】oracle 中随机取一条记录的两种方法
oracle 中随机取一条记录的两种方法 V_COUNT INT:=0; V_NUM INT :=0; 1:TBL_MYTABLE 表中要有一个值连续且唯一的列FID BEGIN SELECT COU ...
- MySQL每个分类的前几条记录
MySQL 获取所有分类和每个分类的前几条记录 比如有文章表 Article(Id,Category,InsertDate) 现在要用SQL找出每种类型中时间最新的前N个数据组成的集合 SELECT ...
- mysql查询各种类型的前N条记录
mysql查询各种类型的前N条记录,将3改为N(需查询条数)即可 (select * from event_info where event_type = 1 limit 3)union all( ...
- Java 获取*.properties配置文件中的内容 ,常见的两种方法
import java.io.InputStream; import java.util.Enumeration; import java.util.List; import java.util.Pr ...
- MySQL取每组的前N条记录
一.对分组的记录取前N条记录:例子:取前 2条最大(小)的记录 .用子查询: SELECT * FROM right2 a WHERE > (SELECT COUNT(*) FROM right ...
- sql 获取每个分组的前N条记录的写法
SELECT * FROM ( --根据 tb表的name进行分组,根据年龄排序 SELECT * , ROW_NUMBER() OVER ( PARTITION BY name ORDER BY a ...
- mysql数据库自增id重新从1排序的两种方法
mysql默认自增ID是从1开始了,但当我们如果有插入表或使用delete删除id之后ID就会不会从1开始了哦. 使用mysql时,通常表中会有一个自增的id字段,但当我们想将表中的数据清空重新添 ...
- mysql分组取每组前几条记录(排序)
首先来造一部分数据,表mygoods为商品表,cat_id为分类id,goods_id为商品id,status为商品当前的状态位(1:有效,0:无效). CREATE TABLE `mygoods` ...
- mysql分组取每组前几条记录(排名)
1.创建表 create table tb( name varchar(10), val int, memo varchar(20) ); 2.插入数据 insert into tb values(' ...
随机推荐
- iOS开发中对RunLoop的个人心得
从接触iOS到现在也有将近两年了,对iOS中的RunLoop也有了一定的认识,下面讲讲个人对RunLoop的理解. 初识RunLoop RunLoops是与线程相关联的基础部分,一个Run Loo ...
- [转载]Matlab生成Word报告
最近在进行一批来料的检验测试,一个个手动填写报告存图片太慢了,就有了种想要使用Matlab在分析完后数据可以自动生成PDF报告的想法,于是就去网上搜索了相关的资料,发现Matlab中文论坛上有xiez ...
- libcurl 函数curl_easy_perform在release下崩溃的问题
今天遇到一个很奇怪的问题: 工程中用到了libcurl, debug可以正常运行,release每次都崩溃,断到curl_easy_perform这一行.堆栈中也得不到有用信息,于是GOOGLE一番, ...
- java写入和写出EXCEL(含源代码)
这两天帮老师做一个数据库,将所有实验交易的数据导入到数据库中,但是不想天天在实验室里面待着,气氛太压抑,就想着先把数据读进EXCEL中,哪天带到实验室导进去 数据原来是这样的,不同的实验有一个专门的文 ...
- iOS 自定义图片和文字垂直显示按钮<上面是图片,文字显示下面>
#import <UIKit/UIKit.h> @interface VerticalButton : UIButton @end #import "VerticalButton ...
- 一份不错的vue.js基础笔记!!!!
第一章 Vue.js是什么? Vue(法语)同view(英语) Vue.js是一套构建用户界面(view)的MVVM框架.Vue.js的核心库只关注视图层,并且非常容易学习,非常容易与其他库或已有的项 ...
- jquery 清空 iframe 的内容,,iframe自适应高度
$(iframe).contents().find("body").html(""); iframe自适应高度 $("#AllDescription& ...
- apktool+dex2jar+xjad反编译android程序
1 将MyAdroid.apk拷贝到E:\disapk 2 下载apktool1.5.2.tar.bz2 和 apktool-install-windows-r05-ibot.tar.bz2 并解压到 ...
- php count函数
最近被问到一个函数count 1.count("123456") 对应的输出是什么? 2.count(null) 对应的输出是什么? 以前没有认真的考虑,只是心里有一个印象那就是c ...
- django+nginx+xshell简易日志查询,接上<关于《rsyslog+mysql+loganalyzer搭建日志服务器<个人笔记>》的反思>
纠正一下之前在<关于<rsyslog+mysql+loganalyzer搭建日志服务器<个人笔记>>的反思>中说到的PHP+MySQL太慢,这里只是说我技术不好,没 ...