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

时间:2022-09-27 21:54:30

 

项目中有个需求是获取出展会分类下的前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种分类,对应有时间

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

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

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

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

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

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

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

我对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

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

同理把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条记录的两种方法浅析的更多相关文章

  1. 【转】oracle 中随机取一条记录的两种方法

    oracle 中随机取一条记录的两种方法 V_COUNT INT:=0; V_NUM INT :=0; 1:TBL_MYTABLE 表中要有一个值连续且唯一的列FID BEGIN SELECT COU ...

  2. MySQL每个分类的前几条记录

    MySQL 获取所有分类和每个分类的前几条记录 比如有文章表 Article(Id,Category,InsertDate) 现在要用SQL找出每种类型中时间最新的前N个数据组成的集合 SELECT ...

  3. mysql查询各种类型的前N条记录

    mysql查询各种类型的前N条记录,将3改为N(需查询条数)即可  (select * from event_info where event_type = 1  limit 3)union all( ...

  4. Java 获取&ast;&period;properties配置文件中的内容 ,常见的两种方法

    import java.io.InputStream; import java.util.Enumeration; import java.util.List; import java.util.Pr ...

  5. MySQL取每组的前N条记录

    一.对分组的记录取前N条记录:例子:取前 2条最大(小)的记录 .用子查询: SELECT * FROM right2 a WHERE > (SELECT COUNT(*) FROM right ...

  6. sql 获取每个分组的前N条记录的写法

    SELECT * FROM ( --根据 tb表的name进行分组,根据年龄排序 SELECT * , ROW_NUMBER() OVER ( PARTITION BY name ORDER BY a ...

  7. mysql数据库自增id重新从1排序的两种方法

    mysql默认自增ID是从1开始了,但当我们如果有插入表或使用delete删除id之后ID就会不会从1开始了哦.   使用mysql时,通常表中会有一个自增的id字段,但当我们想将表中的数据清空重新添 ...

  8. mysql分组取每组前几条记录&lpar;排序&rpar;

    首先来造一部分数据,表mygoods为商品表,cat_id为分类id,goods_id为商品id,status为商品当前的状态位(1:有效,0:无效). CREATE TABLE `mygoods` ...

  9. mysql分组取每组前几条记录&lpar;排名&rpar;

    1.创建表 create table tb( name varchar(10), val int, memo varchar(20) ); 2.插入数据 insert into tb values(' ...

随机推荐

  1. zookeeper原理解析-数据存储

    Zookeeper内存结构 Zookeeper是怎么存储数据的,什么机制保证集群中数据是一致性,在网络异常,当机以及停电等异常情况下恢复数据的,我们知道数据库给我们提供了这些功能,其实zookeepe ...

  2. 原版ubuntu 系统下,emacs24无法输入中文问题解决方案

    在重装了原版ubuntu14后,安装了搜狗输入法,但是意外的发现在emacs下无法使用.在网上查找了一些教程后,解决了该问题.解决方案如下: $sudo mv /usr/bin/emacs24 /us ...

  3. EOF是什么?

    转自http://www.ruanyifeng.com/blog/2011/11/eof.html 学习C语言的时候,遇到的一个问题就是EOF. 它是end of file的缩写,表示"文字 ...

  4. 测缘分程序c代码简单实现

    #include<stdio.h>#include<stdlib.h>#include<math.h> #include <windows.h>//后面 ...

  5. HDU1257-最少拦截系统

    描述: 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来 ...

  6. WEB开发中常用的正则表达式集合

    在计算机科学中,正则表达式用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串.在WEB开发中,正则表达式通常用来检测.查找替换某些符合规则的字符串,如检测用户输入E-mai格式是否正确,采集符 ...

  7. Terminating app due to uncaught exception &&num;39&semi;NSInvalidArgumentException&&num;39&semi;&comma; reason&colon; &&num;39&semi;-&lbrack;NSInvocation setArgument&colon;atIndex&colon;&rsqb;&colon; index &lpar;3&rpar; out of bounds &lbrack;-1&comma; 2&rsqb;&&num;39&semi;

    这是相机调用方法的时候参数错误

  8. 【FlashPlayer】-Debug版本-开发人员推荐

    Adobe的Flash-Player的版本分为“普通版本”和“Debug版本”,后者可以协助开发者测试和调试程序. 那么,先给出Debug版本的下载地址:http://www.adobe.com/su ...

  9. 蚂蚁爬杆问题 UVA 10881

    算法入门经典训练指南上的题. 这里有必要讲一下蚂蚁爬杆问题:每只蚂蚁都有一个初始方向,相撞会转向,关键就是相撞的处理,由于速度并不会改变,两只蚂蚁相撞,可以看做,两只蚂蚁穿过对方,继续沿原方向前进,经 ...

  10. Asp&period;Net Core使用System&period;Drawing&period;Common部署到docker报错问题

    Asp.Net Core 2.1发布后,正式支持System.Drawing.Common绘图了,可以用来做一些图片验证码之类的功能.但是把网站部署到docker容器里运行会遇到很多问题,也是非常闹心 ...