MYSQL SQL级别动态拼接SQL语句

MYSQL 动态SQL语句

最近在公司遇到一个业务需求,该需求大概是这样子的,查询表中最热门的数据。排序规则是根据转发量,推荐量,点赞量排序,并拿去第一条数据。如果表中的所有数据的转发量都为0的情况下则用推荐量排序,也就是说三个中选一个排序并获取第一条数据。排序的优先级分别为 转发量>推荐量>点赞量

首先为了模拟需求,我们将来建立一张话题表

-- ----------------------------
-- Table structure for `topic`
-- ----------------------------
DROP TABLE IF EXISTS `topic`;
CREATE TABLE `topic` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(63) DEFAULT NULL COMMENT '标题名称',
  `share_count` int(11) DEFAULT '0' COMMENT '转发量',
  `recommend_count` int(11) DEFAULT '0' COMMENT '推荐量',
  `like_count` int(11) DEFAULT '0' COMMENT '点赞量',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of topic
-- ----------------------------
INSERT INTO `topic` VALUES ('1', '明天吃什么', '0', '0', '999');
INSERT INTO `topic` VALUES ('2', '后天吃什么', '0', '0', '500');
INSERT INTO `topic` VALUES ('3', '今天吃什么', '0', '0', '200');

可以看到上面这张话题表除了有话题标题转发量推荐量点赞量之外还有作者对吃什么这件事情上很执着。

有了表之后我们就可以快乐的写sql语句了。
思路
经过一顿分析,不难发现该SQL主要的难点在排序(如果觉得获取一条数据是难点的话,就关了这篇文章,当没来过 ),排序要求的优先级是转发量>推荐量>点赞量。也就是说当表里的数据都没有转发量的时候则改为推荐量排序,以此类推…那么这很简单,首先我们要知道表里的数据是否没有转发量,我们可以通过MAX() 聚合函数来判断,如果该表中最大的转发量不等于0则代表有转发量可排序,如果最大的转发量等于0的话那就用推荐量排序,以此类推…
那么判断条件已经有了,那么怎么去实现切换排序呢?使用CASE语句来实现。
最后使用LIMIT 来限制获取条数就好

画外音:我相信到这边我就已经跑偏了,因为我想介绍case语句的用法…

CASE 语句很像JAVA的switch语句…

CASE WHEN [条件表达式]
THEN
	返回的值
WHEN [条件表达式]
THEN
	返回的值
ELSE 
	返回的值
END;

好了,为了今晚我能睡觉,我们还是回到正题吧,CASE语句自己去找博客看,如果看不懂的话就关了这篇文章,当没来过

实现方式

SELECT *
FROM topic #一个简单的查询语句
ORDER BY #排序
CASE WHEN (SELECT MAX(share_count) FROM topic) != 0 #如果话题表的最大转发量不等于0则用转发量排序
THEN
	share_count
WHEN (SELECT MAX(recommend_count) FROM topic) != 0  #否则如果话题表的最大推荐量不等于0则用推荐量排序
THEN
	recommend_count
ELSE #实在不行就点赞量吧。一篇文章要是连点赞量都没有,那就...跟我差不多了。
	like_count	
END
DESC #降序
LIMIT 1; #限制获取条数

结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191223231359864.png

好的,到这里就结束了??? 不好意思并没有。

在我了解到这个需求的时候,我当时的一个思路并不是想着这么写(可能是真的笨,没想到… ) 当时的想法是我能不能够在SQL层面上做到动态拼接SQL???,如果可以的话,那岂不很强。所以我就去网上找了资料,发现还真可以!!!

以上都是废话,这篇文章的正题才正式开始!!!

MYSQL SQL级别动态拼接SQL语句

还是刚刚那需求,但相信我,这次的操作和上面不同,绝对区别于市面上的妖艳贱货。

思路:


SET @lsql = 'SELECT * FROM topic ORDER BY ? DESC LIMIT 1'; #定义一个变量存储要执行的sql语句 
SET @sort_field = #定义一个变量 存储要排序的字段。
CASE WHEN (SELECT MAX(share_count) FROM topic) != 0 
THEN
	CONCAT('share_count')
WHEN (SELECT MAX(recommend_count) FROM topic) != 0  #否则如果话题表的最大推荐量不等于0则用推荐量排序
THEN
	CONCAT('recommend_count')
ELSE #实在不行就点赞量吧。一篇文章要是连点赞量都没有,那就...跟我差不多了。
	CONCAT('like_count')
END;

PREPARE stms FROM @lsql; #预编译这条字符串sql。
EXECUTE stms USING @sort_field;  #执行这条SQL

结果
在这里插入图片描述
这种相对于上一种来说更加灵活,他可以动态的拼接语句,不仅可以作用在排序,也可以动态的拼接WHERE条件等等…更加灵活多变。但这种一般都是封装在存储过程中使用的,而我也是写了一个demo,一个思路。

原创文章 35 获赞 14 访问量 4778

猜你喜欢

转载自blog.csdn.net/weixin_39128265/article/details/103674850
今日推荐