需求说明
数据上一条下一条,是个老需求了 ,大多数是用在新闻类的功能上,一个数据列表按照一定条件然后按固定的一些字段排序,并且只给文章id参数,查过很多文章,多数都是用id进行排序的,不太符合我得需求,于是自己搞了几个小时,测试出来一个sql ,比较稳妥,扩展性强,理论可以随便写附加条件。
操作
图片总是上传失败,这里就上字段了
`id` bigint(32) unsigned NOT NULL AUTO_INCREMENT COMMENT ' 主键 ',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`is_delete` int(1) NOT NULL DEFAULT '0' COMMENT '数据开启状态,',
`type` varchar(64) NOT NULL DEFAULT '' COMMENT '类型new:新闻;certificate:消息;encyclopedia:百科;staggerer:事件;',
`title` varchar(250) NOT NULL DEFAULT '' COMMENT '标题',
`text_body` longtext NOT NULL COMMENT '正文',
`remark` varchar(1023) NOT NULL DEFAULT '' COMMENT '摘要',
`release_time` datetime DEFAULT NULL COMMENT '发布时间',
`source` varchar(255) NOT NULL DEFAULT '' COMMENT '来源',
`notice_img` varchar(500) NOT NULL DEFAULT '' COMMENT '缩略图',
`view` int(11) DEFAULT '0' COMMENT '展示数量',
`is_hot` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否热榜(0:否、1:是)',
`hot_num` int(11) NOT NULL DEFAULT '0' COMMENT '热度',
我要根据类型查询条件并按发布时间倒序
select id , type, title, remark, release_time, source from notice nt,( select if(@cur=0 and id=35458,@cur:=id,0)tc,if(@cur <>0 and @pre=0,@pre:=@tpre,0)tp,if(@pre <>0 and @nex=0 and id <>35458,@nex:=id,0)tn,@tpre:=id from notice,(select @cur:=0,@tpre:=0,@pre:=0,@nex:=0)zz where is_delete = 0 and release_time <= curdate() and `type` = 'staggerer' order by release_time desc )d where nt.id=d.tp and d.tp <>0 and d.tp<>35458
这里35458是具体数据的id,语句大概意思是先把数据列表的查询sql写出来按照条件和字段排好序,然后通过mysql 添加数据编号语法来的灵感,定义了4个变量,4个变量分别是当前行@cur,上一条@pre,下一条@nex,以及全程记录上一条数据id的@tpre,这4个变量可以算出上一条、下一条、和当前数据的id,然后再把结果与原表id关联即可,具体怎么就算出来了,各位需要自己好好研究这个sql,找表多查询几次就明白了,我这里也说不清楚。。另外 当数据是列表的头一条是,@pre算出来的结果是当前id,所以末尾要排除当前的id,这样,首条数据的上一条就是空的了。
select id , type, title, remark, release_time, source from notice nt,( select if(@cur=0 and id=35458,@cur:=id,0)tc,if(@cur <>0 and @pre=0,@pre:=@tpre,0)tp,if(@pre <>0 and @nex=0 and id <>35458,@nex:=id,0)tn,@tpre:=id from notice,(select @cur:=0,@tpre:=0,@pre:=0,@nex:=0)zz where is_delete = 0 and release_time <= curdate() and `type` = 'staggerer' order by release_time desc )d where nt.id=d.tn and d.tn <>0
下一条同理,但是当前数据是列表最后一条时,@nex是没有机会得到值的,所以不用单独加排除当前条的条件 理论上这两条sql 适合mysql 所有上一条下一条的场景,但是有个问题是这个sql在计算时按条件全表计算,就算已经提前计算出结果,也依然要把所有符合条件的结果全部计算才会到外层来关联,所以数据足够多得时候,可能会有性能问题,就当前的需求来说,上一条下一条需要的字段 最主要的是id,title,release_time,这三个字段都很小,只要不查正文,应该都没什么大问题。这么写的主要原因是计算上一条下一条整个逻辑我只能拿到当前数据id一个参数,否则能拿到分页参数的话,性能应该更好。 另外这是基于mysql的写法,这里也提供了一个思路,其它的数据库若是能定义出这样的动态参数,应该也是可以这样写的。 如果有大佬能提供优化,请评论留言。如果方法有错,也可以留言 ,我及时改正。
|